I face a very strange crash on Swift.
Xcode 11.3.1
Swift 5
Case 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)
}
}
If I removed code deinitExecution?()
or objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
. It works fine.
Case 2
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))")
}
}
If I removed code objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
. It works fine.
Is this a swift bug?
I think you mis-use
objc_setAssociatedObject
. The documentation says:The key point here is that you need an object, not a class.
The runtime functions
objc_allocateClassPair
andobjc_registerClassPair
just create new runtime classes, not objects. To get an object, you could useNSClassFromString
, callinit()
and then associate the tag with it.A complete running example could be (just a console program, no unit test):
with the following output: