3

In the documentation...

objc_setAssociatedObject

Sets an associated value for a given object using a given key and association policy.

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)

Parameters object The source object for the association.

key The key for the association.

value The value to associate with the key key for object. Pass nil to clear an existing association.

policy The policy for the association. For possible values, see “Associative Object Behaviors.”

What is not clear is, when you call objc_setAssociatedObject() to remove an association, is it necessary to use the same policy as was used to initially set the property? Or does objc_setAssociatedObject() just use the appropriate policy to "undo" the previous set? i am assuming it must ignore the policy, otherwise if you simply setting another value, the previous value would need to have been set using the same policy also. the difference being, that in some cases, the reference count of the currently stored property would be adjusted, in others case it would not.

It's obvious that the system does track it internally, otherwise the generic objc_removeAssociatedObjects() could never work, and ARC would need to know this anyhow to even work.

The reason I need to know personally is for the following code snippets:

typedef const void* associatedPropertyKeyToken;

and

-(NSMutableDictionary*) associatedInfo{
    NSMutableDictionary *result = [self associatedPropertyForKey:NSAsssociatedInfo];
    if (!result) {

        [self retainAssociatedProperty:(result = [NSMutableDictionary dictionary])
                                forKey:NSAsssociatedInfo];
    }
    return result;
}

-(BOOL) associatedPropertyForKeyExists:(associatedPropertyKeyToken)aKey {
#if DEBUG_ASSOCIATED
    BOOL result =
#else
    return
#endif

    objc_getAssociatedObject(self,aKey)!=nil;

#if DEBUG_ASSOCIATED
    NSLog(@"getting associatedPropertyForKeyExists:%@ = %@",NSStringFromAssociatedPropertyKeyToken(aKey),
          result ? @"YES" : @"NO");
    return result;
#endif
}


-(void) assignAssociatedProperty:(id)prop forKey:(associatedPropertyKeyToken)aKey{
#if DEBUG_ASSOCIATED
    NSLog(@"assigning associatedPropertyForKey:%@ <= %@",NSStringFromAssociatedPropertyKeyToken(aKey),
          prop);
#endif
    objc_setAssociatedObject(self,aKey, prop, OBJC_ASSOCIATION_ASSIGN);
}

-(void) retainAssociatedProperty:(id)prop forKey:(associatedPropertyKeyToken)aKey{
#if DEBUG_ASSOCIATED
    NSLog(@"retaining associatedPropertyForKey:%@ <= %@",NSStringFromAssociatedPropertyKeyToken(aKey),
          prop);
#endif
    objc_setAssociatedObject(self, aKey, prop, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(void) removeAssociatedPropertyForKey:(associatedPropertyKeyToken)aKey{
#if DEBUG_ASSOCIATED
    NSLog(@"removing associatedPropertyForKey:%@",NSStringFromAssociatedPropertyKeyToken(aKey));
#endif
    objc_setAssociatedObject(self,aKey,  NULL, OBJC_ASSOCIATION_ASSIGN);
}
unsynchronized
  • 4,828
  • 2
  • 31
  • 43
  • it is very easy to test it out, why not try it? set object with assign policy and remove it with retain policy, I expected crash if policy matters. – Bryan Chen Nov 12 '13 at 04:00
  • @BryanChen ever tried testing explicitly releasing something under ARC? – unsynchronized Nov 12 '13 at 04:00
  • 1
    how does this related to ARC? and yes I sometimes do manual mamagement management in ARC because I have to deal with C/C++ library – Bryan Chen Nov 12 '13 at 04:03
  • @BryanChen good point. I was mainly tagging it as ARC related as it was at the back of my mind that i wanted to ensure there were no issues under ARC. – unsynchronized Nov 12 '13 at 04:23
  • I would also like to know if this is "ARC-compatible". For instance associating a new object with `OBJC_ASSOCIATION_RETAIN` would automatically release the previous one? For an object associated with `OBJC_ASSOCIATION_ASSIGN` will the reference get automatically `nil`ed? Will `dealloc` automatically clean up all associated objects? etc. – Rivera Mar 25 '14 at 07:48

1 Answers1

4

The policy parameter of objc_setAssociatedObject specifies how the runtime should treat the value parameter of the same function call, and not how it should treat any other object (such as a prior or future value for the same key). Thus the policy given when you associate value is the policy used when you disassociate value.

You can verify that the implementation behaves this way because the source code for the Objective-C runtime is open source. You can find the code that handles associative references in objc-references.mm. The functions of interest are _object_set_associative_reference, which calls ReleaseValue, which calls releaseValue.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • 1
    Thanks, so assuming objc_setAssociatedObject() is a direct wrapper around _object_set_associative_reference(), i can see from looking at the code in objc-references.mm, that my assumption is correct - policy is ignored when value is nil. – unsynchronized Nov 12 '13 at 04:16