對象關(guān)聯(lián)的使用objc_setAssociatedObject

特性

objective-c中,有類別可以在不修改源碼的基礎(chǔ)上增加方法;近排在看別人的開源代碼時,發(fā)現(xiàn)還可以動態(tài)增加屬性。而且是在運行時,太牛B了。

使用運行時庫,必須要先引入 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的運行時函數(shù):objc_setAssociatedObject來把一個對象與另外一個對象進行關(guān)聯(lián)。該函數(shù)需要四個參數(shù):源對象,關(guān)鍵字,關(guān)聯(lián)的對象和一個關(guān)聯(lián)策略。當然,此處的關(guān)鍵字和關(guān)聯(lián)策略是需要進一步討論的。

關(guān)鍵字是一個void類型的指針。每一個關(guān)聯(lián)的關(guān)鍵字必須是唯一的。通常都是會采用靜態(tài)變量來作為關(guān)鍵字。

關(guān)聯(lián)對象可以作為作為一個讓源對象持有這個關(guān)鍵對象的方法(相當于將關(guān)鍵對象通過源對象傳遞),比如下面的label中的顏色,其中的objc_setAssociatedObject是將關(guān)聯(lián)的對象傳出,通過方法objc_getAssociatedObject(id object, const void *key) 獲取到,例如下面的View中的block,是將block在objc_setAssociatedObject中定義,而在objc_getAssociatedObject得到block后實現(xiàn)。

關(guān)聯(lián)策略表明了相關(guān)的對象是通過賦值,保留引用還是復(fù)制的方式進行關(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 實現(xiàn)添加屬性

屬性 其實就是get/set 方法。我們可以使用? objc_setAssociatedObject/objc_getAssociatedObject? 實現(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的擴展

.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的擴展

.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),就是說一個對象可以保持對另一個對象的引用,并獲取那個對象。有了這些,就能實現(xiàn)屬性功能了。 policy可以設(shè)置為以下這些值:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,044評論 0 9
  • 沒了他的日子里 生活是照樣平淡 愛他也只是我的心甘情愿 難為我的一廂情愿 最后一個愿望 和他做朋友 是否能夠?qū)崿F(xiàn)
    luna_tic閱讀 274評論 0 0
  • 山本耀司:我投一下一枚炸彈Yohji Yamamoto 分享一 在女人身上,男人只要看到一絲膨脹的自我,便會厭倦她...
    Yohji閱讀 360評論 0 0

友情鏈接更多精彩內(nèi)容