程序的Swift版本编译并运行没有任何错误。但是,它似乎在包含“as!TSLTransponderDataReceivedBlock”的行重复,其结果如该行右侧所示。程序执行永远不会超过该行代码。如果注释掉这个特定的闭包,那么代码的其余部分似乎按预期运行,除了缺少的功能。
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)
....
}
非常感谢您的建议 - 谢谢。
“弱自我?” inventory.Responder!.transponderDataReceivedBlock引用的前缀被删除,这没有什么区别。此外,闭包中的所有代码都被删除,只留下实际的闭包结构,甚至空闭包也显示出相同的行为。由于TSLTransponderDataReceivedBlock是在原始的Objective-C API源代码中定义和处理的,因此很可能Swift如何设置Obj-C的闭包结构使用。
使用“跳转到定义”的TSLTransponderDataReceivedBlock的Objective-C定义是:
///
/// 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 :(得分:0)
此问题的解决方案如下:
1)更改: 作为! TSLTransponderDataReceivedBlock 至: } 评论:消除&#34; as!&#34;说明符
2)变化: weakSelf?.inventoryResponder!.transponderDataReceivedBlock = {(transponder:TSLTransponderData,moreAvailable:Bool) - &gt;无效
要: inventoryResponder!.transponderDataReceivedBlock = {(_ transponder:TSLTransponderData?,_ moreAvailable:Bool) - &gt;无效
评论:删除weakSelf?参考
注意:最终的工作版本是使用Xcode 9 Beta 4 / Swift 4
完成的