特性
objective-c中,有類別可以在不修改源碼的基礎(chǔ)上增加方法洁墙;近排在看別人的開源代碼時蛹疯,發(fā)現(xiàn)還可以動態(tài)增加屬性。而且是在運(yùn)行時,太牛B了热监。
使用運(yùn)行時庫捺弦,必須要先引入 objc/runtime.h
可以使用的函數(shù)如下:
OBJC_EXPORT?void?objc_setAssociatedObject(id?object,?const?void?*key,?id?value,?objc_AssociationPolicy?policy)
創(chuàng)建關(guān)聯(lián)要使用到Objective-C的運(yùn)行時函數(shù):objc_setAssociatedObject來把一個對象與另外一個對象進(jìn)行關(guān)聯(lián)。該函數(shù)需要四個參數(shù):源對象,關(guān)鍵字列吼,關(guān)聯(lián)的對象和一個關(guān)聯(lián)策略幽崩。當(dāng)然,此處的關(guān)鍵字和關(guān)聯(lián)策略是需要進(jìn)一步討論的寞钥。
關(guān)鍵字是一個void類型的指針慌申。每一個關(guān)聯(lián)的關(guān)鍵字必須是唯一的。通常都是會采用靜態(tài)變量來作為關(guān)鍵字理郑。
關(guān)聯(lián)對象可以作為作為一個讓源對象持有這個關(guān)鍵對象的方法(相當(dāng)于將關(guān)鍵對象通過源對象傳遞)蹄溉,比如下面的label中的顏色,其中的objc_setAssociatedObject是將關(guān)聯(lián)的對象傳出您炉,通過方法objc_getAssociatedObject(id object, const void *key) 獲取到类缤,例如下面的View中的block,是將block在objc_setAssociatedObject中定義邻吭,而在objc_getAssociatedObject得到block后實(shí)現(xiàn)餐弱。
關(guān)聯(lián)策略表明了相關(guān)的對象是通過賦值,保留引用還是復(fù)制的方式進(jìn)行關(guān)聯(lián)的囱晴;還有這種關(guān)聯(lián)是原子的還是非原子的膏蚓。這里的關(guān)聯(lián)策略和聲明屬性時的很類似。這種關(guān)聯(lián)策略是通過使用預(yù)先定義好的常量來表示的畸写。
這個函數(shù)
OBJC_EXPORT?id?objc_getAssociatedObject(id?object,?const?void?*key)
__OSX_AVAILABLE_STARTING(__MAC_10_6,?__IPHONE_3_1);
使用場景
1.category使用 objc_setAssociatedObject/objc_getAssociatedObject 實(shí)現(xiàn)添加屬性
屬性 其實(shí)就是get/set 方法驮瞧。我們可以使用? objc_setAssociatedObject/objc_getAssociatedObject? 實(shí)現(xiàn) 動態(tài)向類中添加 方法
UILabel+Associate.h
#import <UIKit/UIKit.h>
@interface UILabel (Associate)
- (void) setFlashColor:(UIColor *) flashColor;
- (UIColor *) getFlashColor;
@end
UILabel+Associate.m
#import"UILabel+Associate.h"
#import<object/runtime.h>
@implementationUILabel (Associate)
static char flashColorKey;
- (void) setFlashColor:(UIColor *) flashColor{
objc_setAssociatedObject(self,&flashColorKey, flashColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *) getFlashColor{
return objc_getAssociatedObject(self, &flashColorKey);
}@end
調(diào)用代碼:
UILabel *lab =[[UILabel alloc] init];
[lab setFlashColor:[UIColor redColor]];
NSLog(@"%@", [lab getFlashColor]);
2.objc_setAssociatedObject與Block的簡單使用
UIAlertView的擴(kuò)展
.h文件
#import <UIKit/UIKit.h>
typedf void(^successBlock)(NSInteger buttonIndex);
@interface UIAlertView(Block)
- (void)showWithBlock:(successBlock)block;
@end
.m文件
#import"UIAlertView+Block.h"
#import
static const char?alertKey;
@implementationUIAlertView(Block)
- (void)showWithBlock:(successBlock)block{
if(block)? ? {? ? ? ??
objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
self.delegate=self;? ??
}? ?
?[self show];}
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{? ? successBlock block = objc_getAssociatedObject(self, &alertKey);? ??
block(buttonIndex);}
@end
UIButton的擴(kuò)展
.h文件
#import
typedef void(^btnBlock)();
@interfaceUIButton(Block)
- (void)handelWithBlock:(btnBlock)block;
@end
.m文件
#import"UIButton+Block.h"
#import <objc/runtime.h>
static const char btnKey;
@implementationUIButton(Block)
- (void)handelWithBlock:(btnBlock)block{
if(block)? ? {? ? ? ??
objc_setAssociatedObject(self, &btnKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);? ?
?}??
? [self addTarget:selfaction:@selector(btnAction) forControlEvents:UIControlEventTouchUpInside];
}
- (void)btnAction{? ?
btnBlock block = objc_getAssociatedObject(self, &btnKey);? ??
block();
}
@end
這兩個方法可以讓一個對象和另一個對象關(guān)聯(lián),就是說一個對象可以保持對另一個對象的引用枯芬,并獲取那個對象论笔。有了這些,就能實(shí)現(xiàn)屬性功能了千所。 policy可以設(shè)置為以下這些值: