aufgerufen wird. In meinem Projekt habe ich Objective-C und Swift-Code. Ich habe einige Objekte mit Eigenschaften, die Blöcke enthalten, um einige UITableView-Konfigurationen zu bereinigen. Die Verwendung funktioniert in Objective-C, stürzt jedoch bei Verwendung von Swift ab.Swift Closure stürzt ab, wenn es als Objective-C-Block
Ich habe das Problem reduziert, um so minimal wie möglich zu sein, während immer noch reproduzierbar.
// 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)")
...
}
ich am Ende EXC_BAD_ACCESS
bekommen, so vermute ich, es hat etwas mit etwas zu tun hat, gelöst wird, wenn es nicht soll, aber ich kann nicht herausfinden, was ich falsch mache.
Der Stack-Trace ist ganz minimal:
* 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
Allerdings, wenn ich den Block ändern, um eine Zeichenfolge als Parameter wollen:
// 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
}
ich viel mehr zu sagen Stack-Trace erhalten:
* 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
edit: Ich dachte ursprünglich, es hätte etwas damit zu tun, asynchron aufgerufen zu werden, aber es war r Ich konnte es direkt danach direkt aufrufen, also reparierte ich den Code und die Stack-Spur, um das zu berücksichtigen.
Noch besser wäre es zu verwenden? eher, als !. Auf diese Weise kann der Swift-Compiler Ihnen helfen, Code zu schreiben, der nicht auf nil zugreift und nicht zur Laufzeit herausfindet. –
Ich stimme zu, das wäre besser, wenn Swift nur Code schreiben würde. Für den "inString", ja, das ist wahrscheinlich eine gute Idee. Für den Rückgabewert ist a! ist eigentlich erforderlich. ? ist eigentlich ein Kompilierfehler. Die automatisch generierte Signatur für 'MyClass's Block ist' var block: ((String!) -> String!)! {get set} 'gemäß der Schnellhilfe. – cjwirth
Wir warteten nur die Hälfte des Tages herauszufinden, was das Problem ist und es war es:/Danke, Männer! –