首页 > 解决方案 > 使用 Typhoon 在运行时注入闭包时的 EXC_BAD_ACCESS

问题描述

我有一个混合的 ObjC 和 Swift iOS 项目。

我有一个类用于在运行时测试一个普通闭包的注入:

@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")
    }
}

我的 Typhoon 程序集文件包含这个函数:

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
}

我尝试按如下方式使用此闭包:

let closureTester1: TyphoonClosureTester = assembler.testAClosure(closure: {
    NSLog(" closure 1 called!")
}) as! TyphoonClosureTester

// causes EXC_BAD_ACCESS
closureTester1.callClosure()

但这导致EXC_BAD_ACCESS当我调用闭包时。(确切的消息是Thread 1: EXC_BAD_ACCESS (code=1, address=0x0))所以看起来闭包正在某个地方被释放。

我尝试将捕获添加到程序集中(即[closure]),但没有区别:

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
}

我还尝试将闭包作为属性注入,而不是通过 init,它没有任何区别。

标签: typhoon

解决方案


从内存来看,这是不支持的。您可以尝试在测试用例中查找示例。

此处描述了注入包装的原语:https ://github.com/appsquickly/typhoon/wiki/wrap-primitive-values-into-NSValue

. . 但是没有提到块/闭包。

如果您描述了您想要实现的目标,则可以建议下一个最佳解决方法。


推荐阅读