简体   繁体   English

Swift MultipeerConnectivity无条件崩溃DateComponentsBridgeFromObjectiveC

[英]Swift MultipeerConnectivity crash DateComponents unconditionallyBridgeFromObjectiveC

I have a repeatable crash that ends in a EXC_BREAKPOINT like in the image below: 我有一个可重复的崩溃,以EXC_BREAKPOINT结尾,如下图所示:

MultipeerConnectivity崩溃

Steps to reproduce the crash: 重现崩溃的步骤:

  1. Connect two devices 连接两个设备
  2. Begin a transfer using func sendResource(at resourceURL: URL, withName resourceName: String, toPeer peerID: MCPeerID, withCompletionHandler completionHandler: ((Error?) -> Void)? = nil) -> Progress? 使用func sendResource开始传输(在resourceURL:URL,withName resourceName:String,toPeer peerID:MCPeerID,withCompletionHandler completionHandler:((Error?) - > Void)?= nil) - > Progress?
  3. Disconnect the device that initiated the transfer by calling func disconnect() 通过调用func disconnect()断开启动传输的设备

Edit: Another way to reproduce the crash, by calling Progress.cancel() Steps: 编辑:通过调用Progress.cancel()来重现崩溃的另一种方法步骤:

  1. Connect two devices 连接两个设备
  2. Begin a transfer and store the Progress object let progress: Progress = session.sendResource(...) 开始传输并存储Progress对象let progress:Progress = session.sendResource(...)
  3. call cancel on the progress object, causing a crash on the other device progress.cancel() 对进度对象调用取消,导致其他设备崩溃progress.cancel()

My code at the line didFinishReceivingResourceWithName: 我在线上的代码didFinishReceivingResourceWithName:

func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL, withError error: Error?) {
    // transfer to local URL
    MusicDownloadRequestor.sharedInstance.finishReceivingSongUploadAtLocalURL(tempUrl: localURL)
}

Doesn't look like my code is called in the stack trace... 看起来我的代码在堆栈跟踪中看起来不像...

* thread #25: tid = 0x806ec, 0x0000000100944af4 libswiftFoundation.dylib`static Foundation.DateComponents._unconditionallyBridgeFromObjectiveC (Swift.Optional<__ObjC.NSDateComponents>) -> Foundation.DateComponents with unmangled suffix "_merged" + 96, queue = 'com.apple.MCSession.callbackQueue', stop reason = EXC_BREAKPOINT (code=1, subcode=0x100944af4)
frame #0: 0x0000000100944af4 libswiftFoundation.dylib`static Foundation.DateComponents._unconditionallyBridgeFromObjectiveC (Swift.Optional<__ObjC.NSDateComponents>) -> Foundation.DateComponents with unmangled suffix "_merged" + 96
frame #1: 0x0000000100114c60 MyAppSwift`@objc NetworkManager.session(MCSession, didFinishReceivingResourceWithName : String, fromPeer : MCPeerID, at : URL, withError : Error?) -> () + 168 at NetworkManager.swift:0
frame #2: 0x00000001a1dda028 MultipeerConnectivity`__79-[MCSession syncCloseIncomingStream:forPeer:state:error:reason:removeObserver:]_block_invoke + 208
frame #3: 0x0000000100c05258 libdispatch.dylib`_dispatch_call_block_and_release + 24
frame #4: 0x0000000100c05218 libdispatch.dylib`_dispatch_client_callout + 16
frame #5: 0x0000000100c12aec libdispatch.dylib`_dispatch_queue_serial_drain + 1136
frame #6: 0x0000000100c08ce0 libdispatch.dylib`_dispatch_queue_invoke + 672
frame #7: 0x0000000100c14e2c libdispatch.dylib`_dispatch_root_queue_drain + 584
frame #8: 0x0000000100c14b78 libdispatch.dylib`_dispatch_worker_thread3 + 140
frame #9: 0x000000018c2a32a0 libsystem_pthread.dylib`_pthread_wqthread + 1288
frame #10: 0x000000018c2a2d8c libsystem_pthread.dylib`start_wqthread + 4

Update #1: added stack trace as text 更新#1:将堆栈跟踪添加为文本

Update #2: Found a possible lead on the crash, here's another crash with unconditionallyBridgeFromObjectiveC 更新#2:在崩溃中找到了可能的领先优势, 这是另一个无条件的BrianFromObjectiveC崩溃

I think that the problem is the URL is being passed to didFinishReceivingResourceWithName as nil but the parameter is non-optional. 我认为问题是URL被传递给didFinishReceivingResourceWithName为nil,但参数是非可选的。 This makes sense, since if the file fails to transfer there will not be a final resting place for the URL. 这是有道理的,因为如果文件无法传输,则URL不会是最终的休息位置。 Is there any way I can fix this or intercept the error? 有什么方法可以解决这个问题或拦截错误吗?

I think this is an Apple bug. 我认为这是一个Apple bug。 Does anyone have a suggestion for doing a work-around? 有没有人建议做一个解决方案?

Using the mix and match feature, I was able to convert my MCSessionDelegate to Objective-C and then pass the parameters to Swift. 使用混合和匹配功能,我能够将我的MCSessionDelegate转换为Objective-C,然后将参数传递给Swift。 After examining the incoming values I confirmed that the variable "localURL" of type URL is actually nil, meaning that it should have been declared as optional. 检查传入的值后,我确认URL类型的变量“localURL”实际上是nil,这意味着它应该被声明为可选。 I submitted a bug report to Apple. 我向Apple提交了一份错误报告。

As a workaround, write your MCSessionDelegate in Objective-C. 要解决此问题,请在Objective-C中编写MCSessionDelegate。 There are a couple of steps to get Objective-C and Swift to work together in the same project, this page explains it very well . 有几个步骤让Objective-C和Swift在同一个项目中一起工作, 这个页面很好地解释了它

Here is my code. 这是我的代码。

My MCSessionDelegate header: 我的MCSessionDelegate标头:

#import <Foundation/Foundation.h>
#import <MultipeerConnectivity/MultipeerConnectivity.h>
@class NetworkMCSessionTranslator;

@interface NetworkMCSessionDelegate : NSObject <MCSessionDelegate>
-(instancetype)initWithTranslator:(NetworkMCSessionTranslator*) trans;
@end

My MCSessionDelegate implementation file: 我的MCSessionDelegate实现文件:

#import "NetworkMCSessionDelegate.h"
#import "MusicAppSwift-Swift.h"

@interface NetworkMCSessionDelegate()
@property (nonatomic) NetworkMCSessionTranslator *translator;
@end

@implementation NetworkMCSessionDelegate

/*
 create a NetworkMCSessionDelegate and pass in a swift translator
 */
-(instancetype)initWithTranslator:(NetworkMCSessionTranslator*) trans{
    if(self = [super init]){
        self.translator = trans;
    }
    return self;
}

/*
 Indicates that an NSData object has been received from a nearby peer.
 */
- (void)session:(MCSession *)session didReceiveData:(NSData *)data fromPeer:(MCPeerID *)peerID{
    [self.translator networkSession:session didReceive:data fromPeer:peerID];
}

/*
 Indicates that the local peer began receiving a resource from a nearby peer.
 */
- (void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progres{
    [self.translator networkSession:session didStartReceivingResourceWithName:resourceName fromPeer:peerID with:progres];
}

/*
 Indicates that the local peer finished receiving a resource from a nearby peer.
 */
- (void)session:(MCSession *)session didFinishReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID atURL:(NSURL *)localURL withError:(NSError *)error{
    [self.translator networkSession:session didFinishReceivingResourceWithName:resourceName fromPeer:peerID at:localURL withError:error];
}

/*
 Called when the state of a nearby peer changes.
 */
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state{
    [self.translator networkSession:session peer:peerID didChange:state];
}

/*
 Called when a nearby peer opens a byte stream connection to the local peer.
 */
- (void)session:(MCSession *)session didReceiveStream:(NSInputStream *)stream withName:(NSString *)streamName fromPeer:(MCPeerID *)peerID{
    // not expecting to see any of this
}

@end

And my Swift file that collects the traffic from the delegate: 我的Swift文件收集来自委托的流量:

import Foundation
import MultipeerConnectivity

@objc class NetworkMCSessionTranslator: NSObject{
    public func networkSession(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState){
        ...
    }

    public func networkSession(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID){
        ...
    }

    public func networkSession(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?){
        // !!! Notice localURL is now an OPTIONAL !!!
    }

    public func networkSession(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress){
        ...
    }

}

Good luck! 祝好运!

Just letting people know that this bug has been fixed with the release of xcode 9 beta 1. According to documentation and my tests, the at localurl parameter is now optional as expected : https://developer.apple.com/documentation/multipeerconnectivity/mcsessiondelegate/1406984-session 只是让人们知道xcode 9 beta 1的发布已经修复了这个bug。根据文档和我的测试,at localurl参数现在是预期的可选项: https//developer.apple.com/documentation/multipeerconnectivity/ mcsessiondelegate / 1406984-会议

Just update to the last version of xcode9 to resolve this issue. 只需更新到xcode9的最新版本即可解决此问题。

In iOS 7 and xcode 8 and above change your function with localURL as optional 在iOS 7和xcode 8及更高版本中,使用localURL作为可选项更改您的功能

Use this function 使用此功能

func session(_ session: MCSession, didFinishReceivingResourceWithName         
resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, 
withError error: Error?) {

    if (localURL != nil) {
       //enter code here
   }
}

Instead of 代替

func session(_ session: MCSession, didFinishReceivingResourceWithName         
resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL, 
withError error: Error?) {

}

so, this function resolve my crashing issue. 所以,这个功能解决了我的崩溃问题。 If there are showing any warning in xcode 8, ignore it. 如果在xcode 8中显示任何警告,请忽略它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在iOS Swift中使用MultipeerConnectivity - Working with MultipeerConnectivity in iOS swift 使用 SKProductDiscount 的 NumberFormatter (_unconditionallyBridgeFromObjectiveC) 崩溃 - Crash using SKProductDiscount's NumberFormatter (_unconditionallyBridgeFromObjectiveC) 使用具有较大差异的 Datecomponents 时崩溃 - Crash while using Datecomponents having larger differences Swift - MultipeerConnectivity类型不符合协议 - Swift - MultipeerConnectivity Type does not conform to protocol Swift 3-要标记的DateComponents。文本有时显示“…” - Swift 3 - DateComponents to Label.Text sometimes displays “…” Swift中的DateComponents返回奇怪的值。 为什么? - DateComponents in Swift returns weird values. Why? 将Date转换为DateComponents函数以在Swift 3中安排本地通知 - Convert Date to DateComponents in function to schedule local notification in Swift 3 XCode Swift - MultiPeerConnectivity / MCAdvertiserAssistant 未呈现连接的接受/拒绝对话 - XCode Swift - MultiPeerConnectivity / MCAdvertiserAssistant not presenting accept / deny dialogue for connections 来自 Calendar.dateComponents 的日期在 Swift 中返回 nil - Date from Calendar.dateComponents returning nil in Swift MultiPeerConnectivity 以编程方式 - MultiPeerConnectivity programmatically
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM