Associative References

Associative References

Associative references, available starting in Mac OS X v10.6, simulate the addition of object instance variables to an existing class. Using associative references, you can add storage to an object without modifying the class declaration. This may be useful if you do not have access to the source code for the class, or if for binary-compatibility reasons you cannot alter the layout of the object.

Associations are based on a key. For any object you can add as many associations as you want, each using a different key. An association can also ensure that the associated object remains valid for at least the lifetime of the source object.

Creating Associations

You use the Objective-C runtime function objc_setAssociatedObject to make an association between one object and another. The function takes four parameters: the source object, a key, the value, and an association policy constant. Of these, the key and the association policy merit further discussion.

  • The key is a void pointer. The key for each association must be unique. A typical pattern is to use a static variable.

  • The policy specifies whether the associated object is assigned, retained, or copied, and whether the association is be made atomically or non-atomically. This pattern is similar to that of the attributes of a declared property (see “Property Declaration Attributes”). You specify the policy for the relationship using a constant (see objc_AssociationPolicyand Associative Object Behaviors).

Listing 6-1 shows how you can establish an association between an array and a string.

Listing 6-1  Establishing an association between an array and a string

static char overviewKey;
 
NSArray *array =
    [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil];
// For the purposes of illustration, use initWithFormat: to ensure
// the string can be deallocated
NSString *overview =
    [[NSString alloc] initWithFormat:@"%@", @"First three numbers"];
 
objc_setAssociatedObject (
    array,
    &overviewKey,
    overview,
    OBJC_ASSOCIATION_RETAIN
);
 
[overview release];
// (1) overview valid
[array release];
// (2) overview invalid

At point 1, the string overview is still valid because the OBJC_ASSOCIATION_RETAIN policy specifies that the array retains the associated object. When the array is deallocated, however (at point 2), overview is released and so in this case also deallocated. If you try to, for example, log the value of overview, you generate a runtime exception.

Retrieving Associated Objects

You retrieve an associated object using the Objective-C runtime function objc_getAssociatedObject. Continuing the example shown in Listing 6-1, you could retrieve the overview from the array using the following line of code:

NSString *associatedObject =
    (NSString *)objc_getAssociatedObject(array, &overviewKey);

Breaking Associations

To break an association, you typically call objc_setAssociatedObject, passing nil as the value.

Continuing the example shown in Listing 6-1, you could break the association between the array and the string overview using the following line of code:

objc_setAssociatedObject(array, &overviewKey, nil, OBJC_ASSOCIATION_ASSIGN);

Given that the associated object is being set to nil, the policy isn’t actually important.

To break all associations for an object, you can call objc_removeAssociatedObjects. In general, however, you are discouraged from using this function because it breaks all associations for all clients. Use this function only if you need to restore an object to “pristine condition.”

Complete Example

The following program combines code from the preceding sections.

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
 
int main (int argc, const char * argv[]) {
 
    @autoreleasepool {
        static char overviewKey;
 
        NSArray *array = [[NSArray alloc]
            initWithObjects:@ "One", @"Two", @"Three", nil];
        // For the purposes of illustration, use initWithFormat: to ensure
        // we get a deallocatable string
        NSString *overview = [[NSString alloc]
            initWithFormat:@"%@", @"First three numbers"];
 
        objc_setAssociatedObject (
            array,
            &overviewKey,
            overview,
            OBJC_ASSOCIATION_RETAIN
        );
        [overview release];
 
        NSString *associatedObject =
            (NSString *) objc_getAssociatedObject (array, &overviewKey);
        NSLog(@"associatedObject: %@", associatedObject);
 
        objc_setAssociatedObject (
            array,
            &overviewKey,
            nil,
            OBJC_ASSOCIATION_ASSIGN
        );
        [array release];
 
    }
    return 0;
}
 
 
 
 

Associative Object Behaviors

Policies related to associative references.

enum {
   OBJC_ASSOCIATION_ASSIGN = 0,
   OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
   OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
   OBJC_ASSOCIATION_RETAIN = 01401,
   OBJC_ASSOCIATION_COPY = 01403
};
Constants
OBJC_ASSOCIATION_ASSIGN

Specifies a weak reference to the associated object.

OBJC_ASSOCIATION_RETAIN_NONATOMIC

Specifies a strong reference to the associated object, and that the association is not made atomically.

OBJC_ASSOCIATION_COPY_NONATOMIC

Specifies that the associated object is copied, and that the association is not made atomically.

OBJC_ASSOCIATION_RETAIN

Specifies a strong reference to the associated object, and that the association is made atomically.

OBJC_ASSOCIATION_COPY

Specifies that the associated object is copied, and that the association is made atomically.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值