typhoon - 使用 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,它没有任何区别。
解决方案
从内存来看,这是不支持的。您可以尝试在测试用例中查找示例。
此处描述了注入包装的原语:https ://github.com/appsquickly/typhoon/wiki/wrap-primitive-values-into-NSValue
. . 但是没有提到块/闭包。
如果您描述了您想要实现的目标,则可以建议下一个最佳解决方法。
推荐阅读
- c# - 无法访问 WindowsXamlHost 控件的 ItemInvoked 事件处理程序
- webpack - 如何更改 CRA 中的 CSS 模块?
- python - 使用 ElementTree (python) 解析 xml 文件时出错
- apiary.io - Dredd - 如何根据 http 状态码修改测试结果?
- c# - 将线程用于非常小的操作会更好,还是总是首选任务?
- swift - SKEmitterNode如何倒带时间?
- java - 如何从另一个类访问片段类中呈现的 TextView 和进度条
- javascript - 如何防止在java脚本上重新刷新页面?
- go - 包的 `init()` 函数中的无限循环 - 好主意还是坏主意?
- ios - Fastlane 扫描在当前测试会话未完成时启动新的测试会话