Search code examples
objective-cswiftunsafeunsafe-pointersassociated-object

Understanding UnsafeRawPointer in objc_setAssociatedObject


I'd like to set n number of associated objects to an object in Swift

My understanding is the usual pattern for the UnsafeRawPointer reference is like this...

static var reference = "someRef"

public func add(to myObject: AnyObject) {
    let adding = ThingToAdd()        
    objc_setAssociatedObject(myObject, &reference, adding, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}

but this wouldn't work for n number of calls to add(to:)

Similarly, the below code works fine if I only call it once per myObject.. However, if I add another associated object in the same way... it replaces the first ThingToAdd with the second. Building a unique string inline does not work. On the simulator it's fine but on a device it's not.

public func add(to myObject: AnyObject) {

    let adding = ThingToAdd()
    var reference = "objectref\(UUID().uuidString)".replacingOccurrences(of: "-", with: "")

    objc_setAssociatedObject(myObject, reference, adding, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

I understand that this is incorrect, however I don't know how to create n number of UnsafeRawPointers in order to store the associated objects with unique references.

Any help / explanation would be greatly appreciated.


Solution

  • Passing reference to the key: UnsafeRawPointer argument of objc_setAssociatedObject passes the address of the variable storage to that function.

    Global variables and static member variables (and only those) are guaranteed to have a fixed address.

    In your first version, the second and all subsequent calls to objc_setAssociatedObject with the same key replace a previous association.

    In your second version, the address of a local variable is passed as key. That address may or may not be the same on subsequent calls. Note that the contents of the string is irrelevant, the key is just a pointer, i.e. the address of that variable.

    If you need to associate a variable number of values with a given object then I would suggest to associate a single NSMutableArray (or NSMutableDictionary) and add the values to that array or dictionary.