Question

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);
}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top