CategoriesでAssociative Referencesを使用してclassに擬似インスタンス変数を追加


ios 3.1とos x 10.6システムでは、アップル社がobjective-cの実行時にassociative referencesを追加しました.
プロパティ.本質的には、オブジェクトごとにoptional dictionaryがあることを意味します.このdictionaryでは
の双曲線コサインを返します.
これは強力な特性であり、特にobjective-cが本来持っていたcategories特性を考慮すると.しかし、
categoriesでは、クラスに追加のインスタンス変数を追加することはできません.associative referencesを使用してクラスに擬似を追加
インスタンス変数は非常に容易になります.
objective-c実行時に提供されるc言語のapiでは、1つのオブジェクトにキー/値ペアを追加し、次の2つを使用できます.
アクセスする方法は次のとおりです.
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) id objc_getAssociatedObject(id object, const void *key) 

上記のメソッドの呼び出しをプロパティのカスタムgetterとsetterメソッドにパッケージすると、apiを使用するユーザーに
完全に不透明な擬似インスタンス変数を実現した.

Using objects to tag UIViews


次の例では、viewのtagとしてオブジェクトを追加したいと考えています(UIViewにすでに存在するtag属性は
intergersタイプのデータを受信すると、制約要因になる場合があります).
次のように「object tag」categoryのクラスを書きます.
@interface UIView (ObjectTagAdditions)

@property (nonatomic, retain) id objectTag;
- (UIView *)viewWithObjectTag:(id)object;

@end

associative referencesを使用すると、プロパティの実装は非常に直接的です.
static const char *ObjectTagKey = "ObjectTag";

@implementation UIView (ObjectTagAdditions)
@dynamic objectTag;

- (id)objectTag {
    return objc_getAssociatedObject(self, ObjectTagKey);
}

- (void)setObjectTag:(id)newObjectTag {
    objc_setAssociatedObject(self, ObjectTagKey, newObjectTag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

...

setメソッドでOBJC_を指定することでASSOCIATION_RETAIN_NONATOMIC、コンパイラに実行時retainを教えてくれました
この変数の値.その他指定できる表示は、OBJC_ASSOCIATION_ASSIGN・、OBJC_ASSOCIATION_COPY_NONATOMICOBJC_ASSOCIATION_RETAINOBJC_ASSOCIATION_COPY; 。 , -viewWithObjectTag:method: , objectTag view:
- (UIView *)viewWithObjectTag:(id)object {
    // Raise an exception if object is nil
    if (object == nil) {
        [NSException raise:NSInternalInconsistencyException format:@"Argument to -viewWithObjectTag: must not be nil"];
    }

    // Recursively search the view hierarchy for the specified objectTag
    if ([self.objectTag isEqual:object]) {
        return self;
    }
    for (UIView *subview in self.subviews) {
        UIView *resultView = [subview viewWithObjectTag:object];
        if (resultView != nil) {
            return resultView;
        }
    }
    return nil;
}