關(guān)聯(lián)對象
給某個object關(guān)聯(lián)一個或多個其他對象逻族,這些對象通過“鍵”來區(qū)分蜻底,我們可以通過這個鍵給這個object綁定一個對象,也可以通過鍵獲取objct綁定對象聘鳞。object身上的一個鍵就對應(yīng)一個關(guān)聯(lián)對象薄辅,所以我們可以給object關(guān)聯(lián)多個對象要拂。類似字典,把關(guān)聯(lián)到object的值理解為字典中的value站楚,這些value通過key來存取脱惰。
設(shè)置關(guān)聯(lián)對象時用的鍵是個“不透明指針”,在設(shè)置關(guān)聯(lián)對象時窿春,若想讓倆個鍵匹配到同一個值拉一,則二者必須是完全相同的指針才行。鑒于此谁尸,存取關(guān)聯(lián)對象用的key通常是一個靜態(tài)全局變量舅踪。
- runtime提供了給我們3個API以管理關(guān)聯(lián)對象(存儲纽甘、獲取良蛮、移除):
objc_setAssociatedObject(object,key,value, objc_AssociationPolicy policy)
id objc_getAssociatedObject(object, key)
-
objc_removeAssociatedObjects(id object)
參數(shù):
object:被關(guān)聯(lián)的對象
key:關(guān)聯(lián)的key,要求唯一
value:關(guān)聯(lián)的對象
objc_AssociationPolicy policy:內(nèi)存管理的策略注: objc_removeAssociatedObjects(id object)函數(shù)移除的是某個對象身上的所有關(guān)聯(lián)的對象悍赢。objc沒有給我們提供移除object身上單個關(guān)聯(lián)對象的函數(shù)决瞳,所以,一般通過objc_setAssociatedObject函數(shù)傳入nil來達(dá)到移除某個關(guān)聯(lián)對象的目的左权。
內(nèi)存管理的策略
關(guān)聯(lián)類型 | 等效的@property |
---|---|
OBJC_ASSOCIATION_ASSIGN | assign |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | nonatomic,retain |
OBJC_ASSOCIATION_COPY_NONATOMIC | nonatomic,copy |
OBJC_ASSOCIATION_RETAIN | retain |
OBJC_ASSOCIATION_COPY | copy |
給category的property添加getter和setter
在category中的使用 @property添加屬性 皮胡,不會生成帶下劃線的成員變量,也不會有setter和getter方法實現(xiàn)赏迟,所以我們通過runtime關(guān)聯(lián)對象的技術(shù)為已經(jīng)存在的類添加“屬性”屡贺,這樣我們只是實現(xiàn)了setter和getter方法,依然不會有帶下劃線的成員變量
#import "Phone.h"
@interface Phone (Info)
@property (nonatomic,copy) NSString *name;
@end
#import "Phone+Info.h"
#import <objc/runtime.h>
//定義常量 必須是C語言字符串
static const char *key = "name";
@implementation Phone (Info)
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, key);
}
@end
#import "ViewController.h"
#import "Phone.h"
#import "Phone+Info.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Phone *phone = [[Phone alloc]init];
phone.name = @"I'm iphone";
NSLog(@"%@",phone.name);
}
@end
log:I'm iphone
給UIButton的category的添加回調(diào)方法
#import <UIKit/UIKit.h>
typedef void(^ButtonClickCallBack) (UIButton *button);
@interface UIButton (Base)
- (void)handleClickCallBack:(ButtonClickCallBack)callBack;
@end
#import "UIButton+Base.h"
#import <objc/runtime.h>
static const char *key = "Click";
@implementation UIButton (Base)
- (void)handleClickCallBack:(ButtonClickCallBack)callBack{
objc_setAssociatedObject(self, key, callBack, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonClicked{
ButtonClickCallBack callBack = objc_getAssociatedObject(self, key);
if (callBack) {
callBack(self);
}
}
@end
#import "ViewController.h"
#import "UIButton+Base.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeContactAdd];
[button setFrame:CGRectMake(100, 100, 100, 100)];
[button handleClickCallBack:^(UIButton *button) {
NSLog(@"button clicked");
}];
[self.view addSubview:button];
}
@end
log: button clicked
參考
Effective+Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼的52個有效方法