当被称为Objective-C块时,Swift结束崩溃
在我的项目中,我有Objective-C和Swift代码。 我有一些对象具有包含块来清除一些UITableViewconfiguration的属性。 使用它在Objective-C中工作,但使用Swift时会崩溃。
我已经将问题减less到尽可能最小,同时仍然是可重复的。
// in Objective-C @interface MyClass : NSObject @property (copy, nonatomic) NSString* (^block)(); - (NSString *)callTheBlock; @end @implementation MyClass - (NSString *)callTheBlock { if (self.block) { return self.block(); } else { return @"There is no spoon"; } } @end // In Swift // I actually have this in my AppDelegate to run when the app starts, but that shouldn't matter class AppDelegate: UIResponder, UIApplicationDelegate { var myClass: MyClass? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { self.myClass = MyClass() self.myClass?.block = { () -> String in NSLog("In Closure") var string = "String From Closure" // <-- "po string" correctly prints the string return string // <-- This is where it crashes } let output = self.myClass?.callTheBlock() NSLog("\(output)") ... }
我最终得到了EXC_BAD_ACCESS
,所以我猜测它在某些情况下会被释放,但我不知道我做错了什么。
堆栈跟踪非常小:
* thread #1: tid = 0x4a8b6a, 0xbff2d9c8, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0xbff2d9c8) * frame #0: 0xbff2d9c8 frame #1: 0xbff2d9e0
但是,如果我改变块想要一个string作为参数:
// MyClass @property (copy, nonatomic) NSString* (^block)(NSString *string); // Using it in Swift self.myClass?.block = { (inString: String!) -> String in NSLog("In Closure") var string = "String From Closure" return string }
我得到了一个更有说服力的堆栈跟踪:
* thread #1: tid = 0x4a9a38, 0x01b07e63 libobjc.A.dylib`objc_release + 19, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x40000013) frame #0: 0x01b07e63 libobjc.A.dylib`objc_release + 19 * frame #1: 0x0005e442 MyApp`MyApp.AppDelegate.(inString=Some) -> (ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool).(closure #1) + 594 at AppDelegate.swift:22 frame #2: 0x0005e4ad MyApp`reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 77 at AppDelegate.swift:19 frame #3: 0x0005cbaa MyApp`partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 90 at AppDelegate.swift:0 frame #4: 0x0005e5e7 MyApp`reabstraction thunk helper from @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 71 at AppDelegate.swift:19 frame #5: 0x0005ce64 MyApp`partial apply forwarder for reabstraction thunk helper from @callee_owned (@in Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@out Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) + 132 at AppDelegate.swift:0 frame #6: 0x0005e7ee MyApp`reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) -> (@owned Swift.ImplicitlyUnwrappedOptional<Swift.String>) to @callee_unowned @objc_block (@unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSString>) -> (@autoreleased Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSString>) + 478 at AppDelegate.swift:19 frame #7: 0x0008fa3f MyApp`-[MyClass callTheBlock](self=0x7beadc50, _cmd=0x000edee6) + 143 at MyClass.m:38 frame #8: 0x0005bcf8 MyApp`MyApp.AppDelegate.application (application=0x7c160390, launchOptions=None, self=0x7c162d50)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool + 1544 at AppDelegate.swift:24 frame #9: 0x0005cf55 MyApp`@objc MyApp.AppDelegate.application (MyApp.AppDelegate)(ObjectiveC.UIApplication, didFinishLaunchingWithOptions : Swift.Optional<ObjectiveC.NSDictionary>) -> Swift.Bool + 101 at AppDelegate.swift:0 frame #10: 0x0090d14f UIKit`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 309 frame #11: 0x0090daa1 UIKit`-[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1810 frame #12: 0x00912667 UIKit`-[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 824 frame #13: 0x00926f92 UIKit`-[UIApplication handleEvent:withNewEvent:] + 3517 frame #14: 0x00927555 UIKit`-[UIApplication sendEvent:] + 85 frame #15: 0x00914250 UIKit`_UIApplicationHandleEvent + 683 frame #16: 0x03b9df02 GraphicsServices`_PurpleEventCallback + 776 frame #17: 0x03b9da0d GraphicsServices`PurpleEventCallback + 46 frame #18: 0x01cf6ca5 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53 frame #19: 0x01cf69db CoreFoundation`__CFRunLoopDoSource1 + 523 frame #20: 0x01d2168c CoreFoundation`__CFRunLoopRun + 2156 frame #21: 0x01d209d3 CoreFoundation`CFRunLoopRunSpecific + 467 frame #22: 0x01d207eb CoreFoundation`CFRunLoopRunInMode + 123 frame #23: 0x00911d9c UIKit`-[UIApplication _run] + 840 frame #24: 0x00913f9b UIKit`UIApplicationMain + 1225 frame #25: 0x0005dbae MyApp`top_level_code + 78 at AppDelegate.swift:12 frame #26: 0x0005dbeb MyApp`main + 43 at AppDelegate.swift:0 frame #27: 0x024e3701 libdyld.dylib`start + 1
编辑:我原本以为这是与被asynchronous调用有关,但它是可复制的,直接调用它之后像这样,所以我修复了代码和堆栈跟踪反映。
我在popup式文档的帮助下计算出来了! 在处理Objective-C时,大部分事情都需要一个!
。 我很确定这是因为Objective-C没有象Swift这样的Optionals概念。
而不是定义我的闭包:
... self.myClass?.block = { (inString: String!) -> String in ...
它在更改为时可以工作:
... self.myClass?.block = { (inString: String!) -> String! in ...
这是有道理的,因为这是popup式文档中推荐的。