Swift MultipeerConnectivity崩溃DateComponents unconditionallyBridgeFromObjectiveC
我有一个可重复的崩溃,以EXC_BREAKPOINT结尾,如下图所示:
重现崩溃的步骤:
- 连接两个设备
- 使用func sendResource(at resourceURL:URL,withName resourceName:String,toPeer peerID:MCPeerID,withCompletionHandler completionHandler:((Error?) – > Void)?= nil) – > Progress?
- 通过调用func disconnect()来断开启动传输的设备
编辑:通过调用Progress.cancel()重现崩溃的另一种方法步骤:
- 连接两个设备
- 开始传输并存储Progress对象, 让进度:Progress = session.sendResource(…)
- 调用取消进度对象,导致其他设备上的崩溃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中显示任何警告,请忽略它。
- iOS检测系统音量水平变化。 私人API或不? AVSystemController_SystemVolumeDidChangeNotification
- 删除UINavigationBar下的1px边框 – 不工作
- 如何使方形视图调整其超视图使用自动布局
- 在tapGesture动作select器中包含协议function – iOS Swift
- 核心数据文件的位置iOS 10
- 在Swift中使用WKWebView进行身份validation
- Swift 3 – Mapbox – 自定义用户位置注释
- 我们是否必须生成并使用客户端库来使用Google App Engine的端点?
- iOS HealthKit如何保存心率(bpm)值? 迅速
- UIPopoverPresentationController以全屏显示popup窗口
- 无法在Xcode中进行debugging:debugging器中将无法使用此模块的debugging信息