drekka drekka - 4 months ago 14
Swift Question

Strange Swift behaviour when using objc_getAssociatedObject()

The behaviour can be observed by placing this code in a playground:

import Foundation
import ObjectiveC

class TestClass {}
var obj = TestClass()

let stringValue = "xyz"
let key = "def"

objc_setAssociatedObject(obj, key, stringValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

//let f = "f"
let returnedString = objc_getAssociatedObject(obj, key)


This works and returns "xyz" from the
objc_getAssociatedObject
call.

However, if you remove the comment from the
let f = "f"
line. The
objc_getAssociatedObject
call now returns nil.

I'm baffled as to how setting a totally unrelated variable can effect the call.

Any ideas?

Answer

Looks like a bug.

The objc_... methods are part of the Objective-C runtime. They shouldn't exist in Swift.

That said they clearly do. So my guess is that there's something happening when you set that method that kicks the runtime, similar to calling synchronize on NSUserDefaults.

Edit: This NSHipster article explains that the ObjC runtime is actually there.

Edit 2: I tried a few experiments, and I'll make your question even weirder. Wrapping the test case inside the object yields the same result. But changing the variable name to an underscore fixes the problem:

let _ = "f"

I bet assigning a variable overwrites whatever runtime associations you set manually. The underscore just tells the compiler that you aren't using the result of the assignment.

Comments