I have a mixed ObjC and Swift iOS project.
I have a class for testing the injection of a trivial closure at runtime:
@objc
class TyphoonClosureTester: NSObject {
@objc var closure: (() -> Void)?
@objc
override init() {}
@objc
init(closure: (() -> Void)?) {
self.closure = closure
}
@objc
func callClosure() {
guard let closure = closure else {
assert(false, "no closure 1")
return
}
closure()
NSLog("Have called closure 1 OK")
}
}
My assembly file for Typhoon contains this function:
func testAClosure(closure: @escaping () -> Void) -> AnyObject {
return TyphoonDefinition.withClass(TyphoonClosureTester.self) { definition in
definition?.useInitializer(#selector(TyphoonClosureTester.init(closure:))) { initializer in
initializer?.injectParameter(with: closure)
}
definition?.scope = .prototype
} as AnyObject
}
And I try using this closure as follows:
let closureTester1: TyphoonClosureTester = assembler.testAClosure(closure: {
NSLog(" closure 1 called!")
}) as! TyphoonClosureTester
// causes EXC_BAD_ACCESS
closureTester1.callClosure()
but this results in EXC_BAD_ACCESS
when I call the closure. (Exact message is Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
) So it looks like the closure is being deallocated somewhere.
I've tried adding capture into the assembly (i.e. [closure]
) but it makes no difference:
func testAClosure(closure: @escaping () -> Void) -> AnyObject {
return TyphoonDefinition.withClass(TyphoonClosureTester.self) { [closure] definition in
definition?.useInitializer(#selector(TyphoonClosureTester.init(closure:))) { [closure] initializer in
initializer?.injectParameter(with: closure)
}
definition?.scope = .prototype
} as AnyObject
}
I also tried injecting the closure as a property, instead of via init, and it made no difference.
From memory this is not supported. You may try looking in the test cases for an example.
Injecting wrapped primitives is described here: https://github.com/appsquickly/typhoon/wiki/wrap-primitive-values-into-NSValue
. . however there's no reference to blocks/closures.
If you describe what you would like to achieve, a next-best workaround could be suggested.