简体   繁体   English

Swift 奇怪的 EXC_BAD_ACCESS 崩溃与 objc_setAssociatedObject 和 objc_registerClassPair

[英]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

Case 1情况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) .如果我删除了代码deinitExecution?()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) .如果我删除了代码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_allocateClassPairobjc_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.

相关问题 objc_setAssociatedObject上的EXC_BAD_ACCESS与-weak_library /usr/lib/libSystem.B.dylib链接器标志 - EXC_BAD_ACCESS on objc_setAssociatedObject with -weak_library /usr/lib/libSystem.B.dylib linker flags Swift 3.0:“objc_setAssociatedObject”问题 - Swift 3.0: “objc_setAssociatedObject” issue objc_setAssociatedObject在iOS中不可用吗? - Is objc_setAssociatedObject not available in iOS? objc_retain EXC_BAD_ACCESS - objc_retain EXC_BAD_ACCESS 在Swift中使用objc_setAssociatedObject时提前调用dealloc / deinit - dealloc/deinit called early when using objc_setAssociatedObject in swift 如何在swift中将void块传递给objc_setAssociatedObject - How do I pass in a void block to objc_setAssociatedObject in swift objc_setAssociatedObject保留原子或非原子 - objc_setAssociatedObject retain atomic or nonatomic 对类对象使用objc_setAssociatedObject是否正确? - Is it correct to use objc_setAssociatedObject for class object? Swift 5.5:Async @objc didPullToRefresh 选择器使应用程序崩溃并出现错误 EXC_BAD_ACCESS - Swift 5.5: Async @objc didPullToRefresh selector crashes app with error EXC_BAD_ACCESS 设置NSString等于另一个时,Objc EXC_BAD_ACCESS - Objc EXC_BAD_ACCESS when setting a NSString equal to another
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM