Obj-C的已有類中痴奏,添加關(guān)聯(lián)對(duì)象存放自定義數(shù)據(jù)

全文引自
《Effective Objective-C 2.0 編寫高質(zhì)量iOS與OS X代碼發(fā)的52個(gè)有效方法》劲妙,旨在為大家提供一點(diǎn)思路掖桦。Github 筆記

涉及到的方法

objc_setAssociatedObject
objc_getAssociatedObject

有時(shí)需要在對(duì)象中存儲(chǔ)相關(guān)信息限府,這時(shí)我們通常會(huì)從對(duì)象所屬的類中繼承一個(gè)子類夺颤,然后改用這個(gè)子類對(duì)象。然而胁勺,并非所有情況都能這么做世澜,有時(shí)候類的實(shí)例可能是由某種機(jī)制所創(chuàng)建的,而開發(fā)者無法令這種機(jī)制創(chuàng)建出自己所寫的子類實(shí)例署穗。Objective-C中有一項(xiàng)強(qiáng)大的特性可以解決此問題寥裂,這就是『關(guān)聯(lián)對(duì)象 Associated Object』。

可以給某對(duì)象關(guān)聯(lián)許多其他對(duì)象案疲,這些對(duì)象通過『鍵』來區(qū)分封恰。存儲(chǔ)對(duì)象值的時(shí)候,可以指明『存儲(chǔ)策略 storage policy』褐啡,用以維護(hù)相應(yīng)的"內(nèi)存管理語義"诺舔。存儲(chǔ)策略由名為objc-AssociationPolicy的枚舉所定定義,包括下面的值备畦,同事累出了與之等效的@property屬性:假如關(guān)聯(lián)對(duì)象成為了屬性低飒,那么它就會(huì)具備對(duì)應(yīng)的語義。

關(guān)聯(lián)類型 等效的屬性@property
OBJC_ASSOCIATION_COPY copy
OBJC_ASSOCIATION_RETAIN retain
OBJC_ASSOCIATION_ASSIGN assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC nonatomic, reatin
OBJC_ASSOCIATION_COPY_NONATOMIC nonatomic,copy
下列方法可以管理關(guān)聯(lián)對(duì)象:
// 此方法以給定的鍵和策略為某對(duì)象設(shè)置關(guān)聯(lián)對(duì)象
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

// 此方法根據(jù)給定的鍵從某對(duì)象中獲取相應(yīng)的關(guān)聯(lián)對(duì)象值
id objc_getAssociatedObject(id object, const void *key)

// 此方法移除所指定對(duì)象的全部關(guān)聯(lián)對(duì)象
void objc_removeAssociatedObjects(id object)

舉例說明

______iOS開發(fā)中懂盐,之前經(jīng)常用到UIAlertView類『現(xiàn)在已經(jīng)過期』褥赊,該類提供了一種標(biāo)準(zhǔn)視圖,可向用戶展示警告信息莉恼。當(dāng)用戶按下按鈕關(guān)閉該視圖時(shí)崭倘,需要用委托協(xié)議(delegate protocol)來處理動(dòng)作,但是类垫,要想設(shè)置好這個(gè)委托機(jī)制司光,就得把創(chuàng)建警告視圖和處理按鈕動(dòng)作的代碼分開。由于代碼分做兩塊悉患,所以讀起來不方便残家。比如說,我們之前使用UIAlertView時(shí)售躁,一般會(huì)這么寫:

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"關(guān)聯(lián)對(duì)象" message:@"添加一個(gè)Block" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil];
[alertView show];

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 0) {
        [self cancelDeal];
    }else{
        [self doDeal];
    }
}

____如果想在同一個(gè)類里坞淮,處理多個(gè)警告信息視圖茴晋,那么代碼就會(huì)變得更為復(fù)雜,我們必須在delegate方法中檢查傳入的alertView參數(shù)回窘,并根據(jù)此選用相應(yīng)的邏輯诺擅。要是能在創(chuàng)建警告視圖的時(shí)候直接把處理每個(gè)按鈕的邏輯都寫好,那就簡(jiǎn)單多了啡直。
____這可以通過關(guān)聯(lián)對(duì)象來做烁涌,創(chuàng)建完警告視圖之后,設(shè)定一個(gè)與之關(guān)聯(lián)的"塊 Block"酒觅,等到執(zhí)行delegate方法時(shí)再將其讀出來撮执。此方案的代碼實(shí)現(xiàn)如下:

#import <objc/runtime.h>
static void * kAlertBlockKey = @"AlertBlockKey";

- (void)showAlert{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"關(guān)聯(lián)對(duì)象" message:@"添加一個(gè)Block" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"好的", nil];
    
    void (^touchAlertBlock)(NSInteger) = ^(NSInteger index) {
        if (index == 0) {
          [self cancelDeal];
        }else{
          [self doDeal];
        }
    };
 
    objc_setAssociatedObject(alertView, kAlertBlockKey, touchAlertBlock, OBJC_ASSOCIATION_COPY);
    
    [alertView show];
}

// UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    void (^alertBlock)(NSInteger) = objc_getAssociatedObject(alertView, kAlertBlockKey);
    
    if (alertBlock) {
        alertBlock(buttonIndex);
    }
}

Tip

上面的例子只是一個(gè)最簡(jiǎn)單的應(yīng)用,可以根據(jù)具體的需求實(shí)現(xiàn)自己想要的結(jié)果舷丹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抒钱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子颜凯,更是在濱河造成了極大的恐慌谋币,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件症概,死亡現(xiàn)場(chǎng)離奇詭異蕾额,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)穴豫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逼友,“玉大人精肃,你說我怎么就攤上這事≈钠颍” “怎么了司抱?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)黎烈。 經(jīng)常有香客問我习柠,道長(zhǎng),這世上最難降的妖魔是什么依鸥? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任胧卤,我火速辦了婚禮勿侯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溶锭。我一直安慰自己,他們只是感情好符隙,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布趴捅。 她就那樣靜靜地躺著垫毙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拱绑。 梳的紋絲不亂的頭發(fā)上综芥,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音猎拨,去河邊找鬼膀藐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛迟几,可吹牛的內(nèi)容都是我干的消请。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼类腮,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼臊泰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蚜枢,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤缸逃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后厂抽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體需频,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年筷凤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昭殉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡藐守,死狀恐怖挪丢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卢厂,我是刑警寧澤乾蓬,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站慎恒,受9級(jí)特大地震影響任内,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜融柬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一死嗦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧粒氧,春花似錦越走、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铜跑。三九已至,卻和暖如春骡澈,著一層夾襖步出監(jiān)牢的瞬間锅纺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工肋殴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留囤锉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓护锤,卻偏偏與公主長(zhǎng)得像官地,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子烙懦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

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