Swift MultipeerConnectivity崩溃DateComponents unconditionallyBridgeFromObjectiveC

我有一个可重复的崩溃,以EXC_BREAKPOINT结尾,如下图所示:

MultipeerConnectivity崩溃

重现崩溃的步骤:

  1. 连接两个设备
  2. 使用func sendResource(at resourceURL:URL,withName resourceName:String,toPeer peerID:MCPeerID,withCompletionHandler completionHandler:((Error?) – > Void)?= nil) – > Progress?
  3. 通过调用func disconnect()来断开启动传输的设备

编辑:通过调用Progress.cancel()重现崩溃的另一种方法步骤:

  1. 连接两个设备
  2. 开始传输并存储Progress对象, 让进度:Progress = session.sendResource(…)
  3. 调用取消进度对象,导致其他设备上的崩溃progress.cancel()

我在代码行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) } 

看起来不像我的代码被称为堆栈跟踪…

 * 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 

更新#1:添加堆栈跟踪文本

更新#2:发现崩溃的可能导致, 这是另一个与unconditionallyBridgeFromObjectiveC崩溃

我认为问题是URL传递给didFinishReceivingResourceWithName为零,但参数是非可选的。 这是有道理的,因为如果文件无法传输,URL就不会有最终的安放地点。 有什么办法可以解决这个问题或拦截错误?

我认为这是一个苹果的错误。 有没有人有做一个解决办法的build议?

使用混合和匹配function,我能够将我的MCSessionDelegate转换为Objective-C,然后将parameter passing给Swift。 在检查传入的值之后,我确认URLtypes的variables“localURL”实际上是零,这意味着它应该被声明为可选的。 我向苹果提交了一个错误报告。

作为一种解决方法,在Objective-C中编写您的MCSessionDelegate。 有两个步骤可以让Objective-C和Swift在同一个项目中一起工作, 这个页面解释得非常好 。

这是我的代码。

我的MCSessionDelegate头:

 #import <Foundation/Foundation.h> #import <MultipeerConnectivity/MultipeerConnectivity.h> @class NetworkMCSessionTranslator; @interface NetworkMCSessionDelegate : NSObject <MCSessionDelegate> -(instancetype)initWithTranslator:(NetworkMCSessionTranslator*) trans; @end 

我的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 

我的Swift文件从代理收集stream量:

 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){ ... } } 

祝你好运!

只是让人们知道这个bug已经被xcode 9 beta 1的版本修复了。根据文档和我的testing,localurl参数现在是可选的,如预期的那样: https : //developer.apple.com/documentation/multipeerconnectivity/ mcsessiondelegate / 1406984-会议

只需更新到最新版本的xcode9来解决这个问题。

在iOS 7和xcode 8及更高版本中,使用localURL作为可选项更改您的function

使用此function

 func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) { if (localURL != nil) { //enter code here } } 

代替

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

所以,这个function解决了我的崩溃问题。 如果在xcode 8中显示任何警告,请忽略它。