Runtime的關(guān)聯(lián)

很多開(kāi)源庫(kù)都使用了關(guān)聯(lián)鞍盗,我們可以不用修改類的定義而為其對(duì)象增加存儲(chǔ)空間肢础。這在我們無(wú)法訪問(wèn)到類的源碼的時(shí)候或者是考慮到二進(jìn)制兼容性的時(shí)候是非常有用喂分。
關(guān)聯(lián)是基于關(guān)鍵字的聚假,因此块蚌,我們可以為任何對(duì)象增加任意多的關(guān)聯(lián),每個(gè)都使用不同的關(guān)鍵字即可膘格。關(guān)聯(lián)是可以保證被關(guān)聯(lián)的對(duì)象在關(guān)聯(lián)對(duì)象的整個(gè)生命周期都是可用的(在垃圾自動(dòng)回收環(huán)境下也不會(huì)導(dǎo)致資源不可回收)峭范。

在類的定義之外為類增加額外的存儲(chǔ)空間

  • objc_setAssociatedObject
/** 
 * Sets an associated value for a given object using a given key and association policy.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * @param value The value to associate with the key key for object. Pass nil to clear an existing association.
 * @param policy The policy for the association. For possible values, see “Associative Object Behaviors.”
 * 
 * @see objc_setAssociatedObject
 * @see objc_removeAssociatedObjects
 */
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);

objc_setAssociatedObject把一個(gè)對(duì)象與另外一個(gè)對(duì)象進(jìn)行關(guān)聯(lián)。該函數(shù)需要四個(gè)參數(shù):源對(duì)象瘪贱,關(guān)鍵字纱控,關(guān)聯(lián)的對(duì)象和一個(gè)關(guān)聯(lián)策略

關(guān)聯(lián)策略
/* Associative References */

/**
 * Policies related to associative references.
 * These are options to objc_setAssociatedObject()
 */
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    //指定一個(gè)弱引用相關(guān)聯(lián)的對(duì)象
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    //強(qiáng)引用關(guān)聯(lián)對(duì)象辆毡,非原子操作
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                            *   The association is not made atomically. */
    //    復(fù)制關(guān)聯(lián)對(duì)象,非原子操作
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                            *   The association is not made atomically. */
    //  強(qiáng)引用關(guān)聯(lián)對(duì)象甜害,原子操作
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    //    復(fù)制關(guān)聯(lián)對(duì)象舶掖,非原子操作
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};

OBJC_ASSOCIATION_ASSIGN 等價(jià)于 @property(assign)。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等價(jià)于 @property(strong, nonatomic)尔店。
OBJC_ASSOCIATION_COPY_NONATOMIC等價(jià)于@property(copy, nonatomic)眨攘。
OBJC_ASSOCIATION_RETAIN等價(jià)于@property(strong,atomic)。
OBJC_ASSOCIATION_COPY等價(jià)于@property(copy, atomic)嚣州。
/** 
//獲取關(guān)聯(lián)的對(duì)象
 * Returns the value associated with a given object for a given key.
 * 
 * @param object The source object for the association.
 * @param key The key for the association.
 * 
 * @return The value associated with the key \e key for \e object.
 * 
 * @see objc_setAssociatedObject
 */
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
//斷開(kāi)關(guān)聯(lián)
//或者直接使用objc_setAssociatedObject函數(shù)期犬,傳入nil值即可
/** 
 * Removes all associations for a given object.
 * 
 * @param object An object that maintains associated objects.
 * 
 * @note The main purpose of this function is to make it easy to return an object 
 *  to a "pristine state”. You should not use this function for general removal of
 *  associations from objects, since it also removes associations that other clients
 *  may have added to the object. Typically you should use \c objc_setAssociatedObject 
 *  with a nil value to clear an association.
 * 
 * @see objc_setAssociatedObject
 * @see objc_getAssociatedObject
 */
OBJC_EXPORT void objc_removeAssociatedObjects(id object)
    OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0);
* 例子
//給一個(gè)可變數(shù)組添加一個(gè)關(guān)聯(lián)
    static char overviewKey;
    NSMutableArray * marrDemo =[[NSMutableArray alloc] initWithObjects:@"1", @"2", @"3", nil];
    NSString * overview = [[NSString alloc] initWithFormat:@"%@",@"First three numbers"];
    objc_setAssociatedObject(marrDemo, &overviewKey, overview, OBJC_ASSOCIATION_RETAIN);
    
//獲取相關(guān)聯(lián)的對(duì)象
    NSString * associatedObject = (NSString *)objc_getAssociatedObject(marrDemo, &overviewKey);

//斷開(kāi)關(guān)聯(lián)
//斷開(kāi)關(guān)聯(lián)是使用objc_setAssociatedObject函數(shù),傳入nil值即可
    objc_setAssociatedObject(marrDemo, &overviewKey, nil, OBJC_ASSOCIATION_RETAIN);

分類避诽,是不能添加屬性的,調(diào)用會(huì)崩潰的璃谨。
查了下文檔發(fā)現(xiàn)沙庐,OC的分類允許給分類添加屬性,但不會(huì)自動(dòng)生成getter佳吞、setter方法拱雏。有沒(méi)有解決方案呢?有底扳,通過(guò)運(yùn)行時(shí)建立關(guān)聯(lián)引用铸抑。

#import <UIKit/UIKit.h>

@interface UIViewController (ICEDemo)

@property (nonatomic, copy) NSString *str;

@end

#import "UIViewController+ICEDemo.h"
#import <objc/runtime.h>

static void *strKey = &strKey;

@implementation UIViewController (ICEDemo)

- (void)setStr:(NSString *)str {
    objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}

-(NSString *)str
{
    return objc_getAssociatedObject(self, &strKey);
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衷模,隨后出現(xiàn)的幾起案子鹊汛,更是在濱河造成了極大的恐慌,老刑警劉巖阱冶,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刁憋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡木蹬,警方通過(guò)查閱死者的電腦和手機(jī)至耻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镊叁,“玉大人尘颓,你說(shuō)我怎么就攤上這事』奁” “怎么了疤苹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蛔添。 經(jīng)常有香客問(wèn)我痰催,道長(zhǎng)兜辞,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任夸溶,我火速辦了婚禮逸吵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缝裁。我一直安慰自己扫皱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布捷绑。 她就那樣靜靜地躺著韩脑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪粹污。 梳的紋絲不亂的頭發(fā)上段多,一...
    開(kāi)封第一講書(shū)人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音壮吩,去河邊找鬼进苍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸭叙,可吹牛的內(nèi)容都是我干的觉啊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼沈贝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼杠人!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宋下,我...
    開(kāi)封第一講書(shū)人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗡善,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后学歧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體滤奈,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年撩满,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蜒程。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡伺帘,死狀恐怖昭躺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伪嫁,我是刑警寧澤领炫,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站张咳,受9級(jí)特大地震影響帝洪,放射性物質(zhì)發(fā)生泄漏似舵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一葱峡、第九天 我趴在偏房一處隱蔽的房頂上張望砚哗。 院中可真熱鬧,春花似錦砰奕、人聲如沸蛛芥。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仅淑。三九已至,卻和暖如春胸哥,著一層夾襖步出監(jiān)牢的瞬間涯竟,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工空厌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昆禽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓蝇庭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親捡硅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子哮内,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容