[英]Swift strange EXC_BAD_ACCESS crash with objc_setAssociatedObject and objc_registerClassPair
I face a very strange crash on Swift.我在 Swift 上遇到了一个非常奇怪的崩溃。
Xcode 11.3.1 Xcode 11.3.1
Swift 5 Swift 5
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)
.如果我删除了代码
deinitExecution?()
或objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
。 It works fine.它工作正常。
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)
.如果我删除了代码
objc_setAssociatedObject(dynamicClass, &associatedDynamicTagHandle, true, .OBJC_ASSOCIATION_ASSIGN)
。 It works fine.它工作正常。
Is this a swift bug?这是 swift 错误吗?
I think you mis-use objc_setAssociatedObject
.我认为您误用
objc_setAssociatedObject
。 The documentation says:文档说:
Sets an associated value for a given object using a given key and association policy.
使用给定的键和关联策略为给定的 object 设置关联值。
The key point here is that you need an object , not a class .这里的关键是您需要一个object ,而不是class 。
The runtime functions objc_allocateClassPair
and objc_registerClassPair
just create new runtime classes, not objects.运行时函数
objc_allocateClassPair
和objc_registerClassPair
只是创建新的运行时类,而不是对象。 To get an object, you could use NSClassFromString
, call init()
and then associate the tag with it.要获得 object,您可以使用
NSClassFromString
,调用init()
然后将标签与其关联。
A complete running example could be (just a console program, no unit test):一个完整的运行示例可能是(只是一个控制台程序,没有单元测试):
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()
with the following output:使用以下 output:
TestObject.init() one TestObject.deinit() deinitExecution InterestTests.deinit() Program ended with exit code: 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.