2017-02-27 51 views
9

我有一個可重複的碰撞,在一個EXC_BREAKPOINT下面的圖像中結束,如:夫特MultipeerConnectivity碰撞DateComponents unconditionallyBridgeFromObjectiveC

MultipeerConnectivity crash

步驟來重現墜毀:

  1. 連接兩個設備
  2. 使用func sendResource開始傳輸(位於resourceURL:URL, withName resourceName:String, toPeer peerID:MCPeerID, withCompletionHandler completionHandler:((Error?) - > Void)? =無) - >進度?
  3. 斷開通過調用FUNC斷開()

編輯發起的傳輸的設備:另一種重現崩潰,通過調用Progress.cancel()步驟:

  1. 連接兩個設備
  2. 開始轉移並存儲進度對象讓進度:進度= session.sendResource(...)
  3. 調用取消進度對象,導致崩潰o n中的其他設備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:實測值的可能的引線在崩潰,here's another crash with unconditionallyBridgeFromObjectiveC

我認爲問題是URL傳遞給didFinishReceivingResourceWithName爲零,但該參數是非可選的。這是有道理的,因爲如果文件無法傳輸,那麼就不會有URL的最終安放位置。有什麼辦法可以解決這個問題或攔截錯誤?

我認爲這是一個蘋果的錯誤。有沒有人有做一個解決辦法的建議?

+0

請將堆棧跟蹤添加爲文本。 –

+0

@ AminNegm-Awad更新,謝謝! – user2821647

回答

4

使用混合匹配功能,我能夠將我的MCSessionDelegate轉換爲Objective-C,然後將參數傳遞給Swift。在檢查傳入的值之後,我確認URL類型的變量「localURL」實際上是零,這意味着它應該被聲明爲可選。我向蘋果提交了一個錯誤報告。

作爲一種解決方法,在Objective-C中編寫MCSessionDelegate。有幾個步驟可以讓Objective-C和Swift在同一個項目中一起工作,this page explains it very well

這是我的代碼。

我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 

我的雨燕文件而收集從委託交通:

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

} 

祝你好運!

1

在iOS系統7的Xcode 8.0及以上更改與localURL的功能爲可選

使用此功能

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?) { 

} 

所以,這個功能解決我的崩潰問題。 如果在xcode 8中顯示任何警告,請忽略它。

+0

請解釋一下? – user1120808