我們知道,在 Objective-C 中可以通過(guò) Category 給一個(gè)現(xiàn)有的類添加屬性迫淹,但是卻不能添加實(shí)例變量秘通。但我們可以通過(guò) Associated Objects 來(lái)彌補(bǔ)這一不足。
相關(guān)函數(shù)
與 Associated Objects 相關(guān)的函數(shù)主要有三個(gè)敛熬,我們可以在 runtime 源碼的 runtime.h 文件中找到它們的聲明:
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void *key);
void objc_removeAssociatedObjects(id object);
-objc_setAssociatedObject
用于給對(duì)象添加關(guān)聯(lián)對(duì)象肺稀,傳入 nil 則可以移除已有的關(guān)聯(lián)對(duì)象;
-objc_getAssociatedObject
用于獲取關(guān)聯(lián)對(duì)象应民;
-objc_removeAssociatedObjects
用于移除一個(gè)對(duì)象的所有關(guān)聯(lián)對(duì)象话原。
key值
一般來(lái)說(shuō),有以下三種推薦的 key 值:
1诲锹、聲明 static char kAssociatedObjectKey;
繁仁,使用 &kAssociatedObjectKey
作為key
值;
2、聲明 static void *kAssociatedObjectKey = &kAssociatedObjectKey;
归园,使用 kAssociatedObjectKey
作為 key
值黄虱;
3、用selector
庸诱,使用 getter 方法的名稱作為key
值捻浦。
三種方式看個(gè)人習(xí)慣都可以。
關(guān)聯(lián)策略
在給一個(gè)對(duì)象添加關(guān)聯(lián)對(duì)象時(shí)有五種關(guān)聯(lián)策略可供選擇:
關(guān)聯(lián)策略 | 等價(jià)屬性 | 說(shuō)明 |
---|---|---|
OBJC_ASSOCIATION_ASSIGN | @property (assign) | 弱引用關(guān)聯(lián)對(duì)象 |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | @property (strong, nonatomic) | 強(qiáng)引用關(guān)聯(lián)對(duì)象桥爽,且為非原子操作 |
OBJC_ASSOCIATION_COPY_NONATOMIC | @property (copy, nonatomic) | 復(fù)制關(guān)聯(lián)對(duì)象朱灿,且為非原子操作 |
OBJC_ASSOCIATION_RETAIN | @property (strong, atomic) | 強(qiáng)引用關(guān)聯(lián)對(duì)象,且為原子操作 |
OBJC_ASSOCIATION_COPY | @property (copy, atomic) | 復(fù)制關(guān)聯(lián)對(duì)象钠四,且為原子操作 |
具體實(shí)現(xiàn)
我將演示用3種key值
@interface UIViewController (AssociatedObjects)
@property (strong, nonatomic) NSString *associatedObject_retain;
@property (copy, nonatomic) NSString *associatedObject_copy;
@property (assign, nonatomic) BOOL associatedObject_assign;
@end
#import "UIViewController+AssociatedObjects.h"
#import "objc/runtime.h"
//聲明key值
static char kAssociatedObject_retain_Key;
static void *kAssociatedObject_copy_Key = &kAssociatedObject_copy_Key;
@implementation UIViewController (AssociatedObjects)
- (NSString *)associatedObject_copy {
return objc_getAssociatedObject(self, kAssociatedObject_copy_Key);
}
- (void)setAssociatedObject_copy:(NSString *)associatedObject_copy {
objc_setAssociatedObject(self, kAssociatedObject_copy_Key, associatedObject_copy, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)associatedObject_retain {
return objc_getAssociatedObject(self, &kAssociatedObject_retain_Key);
}
- (void)setAssociatedObject_retain:(NSString *)associatedObject_retain {
objc_setAssociatedObject(self, &kAssociatedObject_retain_Key, associatedObject_retain, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)associatedObject_assign {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setAssociatedObject_assign:(BOOL)associatedObject_assign {
objc_setAssociatedObject(self, @selector(associatedObject_assign), @(associatedObject_assign), OBJC_ASSOCIATION_ASSIGN);
}
@end