简体   繁体   中英

dealloc/deinit called early when using objc_setAssociatedObject in swift

It appears that objc_setAssociatedObject causes objects to be released early.

I followed the method mentioned here to set the association.

import ObjectiveC

// Define a variable whose address we'll use as key.
// "let" doesn't work here.
var kSomeKey = "s"

…

func someFunc() {
    var value = MyOtherClass()
    objc_setAssociatedObject(target, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))

    let assocValue : AnyObject! = objc_getAssociatedObject(target, &kSomeKey)
}

This results in the object being released during the objc_setAssociatedObject call. As you can see by this stacktrace.

[MyOtherClass dealloc]
_objc_object::sidetable_release(bool)
_object_set_associative_reference
MyApp.MyClass.someFunc()

I originally thought it might have had something to do with swift classes so I also tried standard Objective-C classes and deinit or dealloc are called during the objc_setAssociatedObject call.

Further adding to my confusion is that objc_getAssociatedObject appears to return a valid object and I can access it variables without error.

Is this a swift bug or have I used objc_setAssociatedObject incorrectly?

I am using Xcode6 beta5 in case that is relevant.

I guess your code would not even compile, because you are using "value" twice as a constant name.

This works fine as an AppDelegate in beta 6:

import ObjectiveC

var kSomeKey = "this_is_a_key"

class MyOtherClass {
    var foo = "bar"

    deinit {
        println("deinit")
    }
}

@UIApplicationMain
class AppDelegateTest: UIResponder, UIApplicationDelegate {

    func someFunc() {
        var value = MyOtherClass()
        objc_setAssociatedObject(self, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))

        let value2: AnyObject! = objc_getAssociatedObject(self, &kSomeKey)

        println("type of is \(_stdlib_getTypeName(value2))")

        let value3 = value2 as MyOtherClass

        println("other is " + value3.foo)

        println("end of someFunc()")
    }


    func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
        self.someFunc()

        return true
    }
}

I barely changed anything and the deinit method is never called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM