我在Swift上遇到了一个非常奇怪的崩溃。
Xcode 11.3.1
swift 5
情况1
class TestObject {
var deinitExecution: (() -> Void)?
deinit {
// comment this to avoid crash
deinitExecution?()
}
}
private var associatedDynamicTagHandle: UInt8 = 0
class InterestTests: XCTestCase {
func testExample() {
guard let dynamicClass = objc_allocateClassPair(TestObject.self, "DynamicClass", 0) else {
XCTFail()
return
}
objc_registerClassPair(dynamicClass)
objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
}
}
如果我删除了代码
deinitExecution?()
或objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
。它工作正常。情况二
class TestObject {
}
private var associatedDynamicTagHandle: UInt8 = 0
class InterestTests: XCTestCase {
func testExample() {
guard let dynamicClass = objc_allocateClassPair(TestObject.self, "DynamicClass", 0) else {
XCTFail()
return
}
objc_registerClassPair(dynamicClass)
objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
let method = class_getInstanceMethod(dynamicClass, NSSelectorFromString("aName"))
print("method: \(String(describing: method))")
}
}
如果我删除了代码
objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
。它工作正常。这是一个迅速的错误吗?
最佳答案
我认为您滥用objc_setAssociatedObject
。该文档说:
Sets an associated value for a given object using a given key and association policy.
这里的关键点是您需要一个对象,而不是一个类。
运行时函数
objc_allocateClassPair
和objc_registerClassPair
仅创建新的运行时类,而不创建对象。要获取对象,可以使用NSClassFromString
,调用init()
,然后将标签与其关联。一个完整的正在运行的示例可能是(只是一个控制台程序,没有单元测试):
import Foundation
class TestObject {
var deinitExecution: (() -> Void)?
required init() {
print ("TestObject.init()")
}
deinit {
print ("TestObject.deinit()")
deinitExecution?()
}
}
private var associatedDynamicTagHandle: UInt8 = 0
class InterestTests {
func testExample() {
guard let dynamicClass = objc_allocateClassPair(TestObject.self, "DynamicClass", 0) else {
print("oops")
return
}
objc_registerClassPair(dynamicClass)
let toClass = NSClassFromString("DynamicClass") as! TestObject.Type
let obj = toClass.init()
obj.deinitExecution = { print ("deinitExecution") }
objc_setAssociatedObject(obj, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
}
deinit {
print ("InterestTests.deinit()")
}
}
InterestTests().testExample()
具有以下输出:
TestObject.init() one TestObject.deinit() deinitExecution InterestTests.deinit() Program ended with exit code: 0
关于ios - 带有objc_setAssociatedObject和objc_registerClassPair的Swift奇怪的EXC_BAD_ACCESS崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62027812/