简体   繁体   中英

EXC_BAD_ACCESS when injecting a closure at runtime using Typhoon

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 (ie [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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM