2017-08-17 10 views
0

プログラムのSwiftバージョンはコンパイルされ、エラーなく実行されます。しかし、 "as!TSLTransponderDataReceivedBlock"を含む行で、その行の右側に示されているような結果が繰り返されているようです。プログラムの実行は、そのコード行を過ぎることはありません。この特定のクロージャがコメントアウトされている場合、コードの残りの部分は、機能が不足していることを除いて、期待通りに機能しているようです。Objective-CクロージャはSwiftに変換されますが、エラーなしで繰り返し実行されます。

Objective-C Code that works as expected 
---------------------------------------- 
- (void)viewDidLoad { 
[super viewDidLoad]; 

self.csvString = [NSMutableString stringWithFormat:@"DATE,EPC,FTID,INDX,PC,CRC,RSSI\n"]; 
// Use the single 
_commander = ((TSLAppDelegate *)[UIApplication sharedApplication].delegate).commander; 

// This formatter will convert any timestamps received 
_dateFormatter = [[NSDateFormatter alloc] init]; 
_dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss"; 
_dateFormatter.timeZone = [NSTimeZone localTimeZone]; 

// Note: the weakSelf is used to avoid warning of retain cycles when self is used in Blocks 
__weak typeof(self) weakSelf = self; 


// 
// Performing an inventory could potentially take a long time if many transponders are in range so it is best to handle responses asynchronously 
// 
// The TSLInventoryCommand is also a TSLAsciiResponder for inventory responses and can have a transponderDataReceivedBlock 
// that is informed of each transponder as it is received 

// Create a TSLInventoryCommand 
_inventoryResponder = [[TSLInventoryCommand alloc] init]; 

// 
// Use the TransponderData-based per transponder Block callback 
// 
_inventoryResponder.transponderDataReceivedBlock = ^(TSLTransponderData *transponder, BOOL moreAvailable) 
{ 
    // Append the transponder EPC identifier and RSSI to the results 
    weakSelf.partialResultMessage = [weakSelf.partialResultMessage stringByAppendingFormat:@"Date: %@ EPC: %@ Indx: %@ RSSI: %@\n\n", 
            (transponder.timestamp == nil) ? @"n/a" : [weakSelf.dateFormatter stringFromDate: transponder.timestamp], 
            (transponder.epc == nil) ? @"n/a" : transponder.epc, 
            (transponder.index == nil) ? @"n/a" : [NSString stringWithFormat:@"%04X", transponder.index.unsignedIntValue ], 
            (transponder.rssi == nil) ? @"n/a" : [NSString stringWithFormat:@"%3d", transponder.rssi.intValue] 
            ]; 

    // This line saves the RFID tag info to the string that will be written out to the CSV file. 
    self.csvString = [NSMutableString stringWithFormat:@"%@ %@", self.csvString, weakSelf.fullResultMessage]; 

    weakSelf.transpondersSeen++; 

    // If this is the last transponder add a few blank lines 
    if(!moreAvailable) { 
     weakSelf.partialResultMessage = [weakSelf.partialResultMessage stringByAppendingFormat:@"\nTransponders seen: %4d\n\n", weakSelf.transpondersSeen]; 
     weakSelf.transpondersSeen = 0; 
    } 

    // This changes UI elements so perform it on the UI thread 
    // Avoid sending too many screen updates as it can stall the display 
    if(!moreAvailable || _transpondersSeen < 3 || _transpondersSeen % 10 == 0) { 
     [weakSelf performSelectorOnMainThread: @selector(updateResults:) withObject:weakSelf.partialResultMessage waitUntilDone:NO]; 
     weakSelf.partialResultMessage = @""; 
    } 
}; 


Swift 3 code that keeps repeating and never gets past the end of the closure: 
----------------------------------------------------------------------------- 
override func viewDidLoad() { 
    super.viewDidLoad() 
    csvString = "DATE,EPC,FTID,INDX,PC,CRC,RSSI\n" 
    // Use the single 
    commander = (UIApplication.shared.delegate as? TSLAppDelegate)?.commander 
    // This formatter will convert any timestamps received 
    dateFormatter = DateFormatter() 
    dateFormatter?.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" 
    dateFormatter?.timeZone = NSTimeZone.local 
     // Note: the weakSelf is used to avoid warning of retain cycles when self is used in Blocks 
    weak var weakSelf: TSLInventoryViewController? = self 
    // 
    // Performing an inventory could potentially take a long time if many transponders are in range so it is best to handle responses asynchronously 
    // 
    // The TSLInventoryCommand is also a TSLAsciiResponder for inventory responses and can have a transponderDataReceivedBlock 
    // that is informed of each transponder as it is received 
    // Create a TSLInventoryCommand 
    inventoryResponder = TSLInventoryCommand() 
    // 
    // Use the TransponderData-based per transponder Block callback 
    // 
    // Append the transponder EPC identifier and RSSI to the results 
    weakSelf?.inventoryResponder!.transponderDataReceivedBlock = {(transponder: TSLTransponderData, moreAvailable: Bool) -> Void in 
     weakSelf!.partialResultMessage = weakSelf!.partialResultMessage.appendingFormat("Date: %@ EPC: %@ Indx: %@ RSSI: %@\n\n", 
      (transponder.timestamp == nil) ? "n/a" : (weakSelf!.dateFormatter?.string(from: transponder.timestamp))!, 
      (transponder.epc == nil) ? "n/a" : transponder.epc, 
      (transponder.index == nil) ? "n/a" : String(format: "%04X", CUnsignedInt(transponder.index)), 
      (transponder.rssi == nil) ? "n/a" : String(format: "%3d", CInt(transponder.rssi))) 

     // This line saves the RFID tag info to the string that will be written out to the CSV file. 
     weakSelf?.csvString = "\(weakSelf?.csvString ?? "n/a") \(weakSelf!.fullResultMessage)" 
     weakSelf!.transpondersSeen += 1 
     // If this is the last transponder add a few blank lines 
     if !moreAvailable { 
      weakSelf!.partialResultMessage = weakSelf!.partialResultMessage.appendingFormat("\nTransponders seen: %4d\n\n", weakSelf!.transpondersSeen) 
      weakSelf!.transpondersSeen = 0 
     } 
     // This changes UI elements so perform it on the UI thread 
     // Avoid sending too many screen updates as it can stall the display 
     if !moreAvailable || self.transpondersSeen < 3 || self.transpondersSeen % 10 == 0 { 
      weakSelf!.performSelector(onMainThread: #selector(self.updateResults), with: weakSelf!.partialResultMessage, waitUntilDone: false) 
      weakSelf!.partialResultMessage = "" 
     } 
    } as! TSLTransponderDataReceivedBlock   //Thread 1: EXC_BREAKPOINT (code=1, subcode=0x10003a878) 
.... 
} 

あなたの提案は大変ありがとうございます。ありがとうございました。

「weakSelf?」 .responder!.transponderDataReceivedBlock参照が削除されましたが、これは違いはありませんでした。さらに、クロージャ内のコードはすべて削除され、実際のクロージャ構造だけが残され、空のクロージャでも同じ動作が示されます。 TSLTransponderDataReceivedBlockが定義され、元のObjective-C APIソースコードで処理されているため、SwiftがObj-Cのクロージャー構造を設定する方法に問題がある可能性が高いようです。

"定義へのジャンプ" を使用してからTSLTransponderDataReceivedBlockのObjective-Cの定義は次のとおりです。

1)変更: }として

/// 
/// The block type to handle transponder information received 
/// 
/// @param transponder - the transponder information provided as a TSLTransponderData instance 
/// @param moreAvailable - YES if there are more transponders to be delivered 
/// 
typedef void(^TSLTransponderDataReceivedBlock)(TSLTransponderData *transponder, BOOL moreAvailable); 
+0

で行われましたが、 'TSLInventoryCommand()' '削除を作成した後に、' TSLTransponderDataReceivedBlock' – nayem

+0

の宣言を示し、weakSelf .'ラインから? 'weakSelf?.inventoryResponder!.transponderDataReceivedBlock = {(トランスポンダ:TSLTransponderData、moreAvailable:Bool) - > Void in' – nayem

答えて

0

この問題を解決するには、次のようでした! TSLTransponderDataReceivedBlock To: } コメント: "as!"指定

2)変更: weakSelf .inventoryResponder .transponderDataReceivedBlock = {(トランスポンダ:TSLTransponderData、moreAvailable:?!ブール値) - >

でvoidへ: inventoryResponder .transponderDataReceivedBlock = {(_トランスポンダー:TSLTransponderData! ?、_ moreAvailable:Bool) - >無効にする

コメント:weakSelfを削除しますか?

注参照:最終的な作業のビルドはXcodeの9ベータ4 /スウィフト4

関連する問題