iOS 運(yùn)行時之 Associative(關(guān)聯(lián))

原文地址:http://www.jkeabc.com/649648.html
附:關(guān)聯(lián)對象 AssociatedObject 完全解析http://www.reibang.com/p/79479a09a8c0

iOS 運(yùn)行時之 Associative(關(guān)聯(lián))
iOS 下有很多運(yùn)行時特性,這里介紹一下 Associative(關(guān)聯(lián)) 這個運(yùn)行時特性秘血,以及它一些使用場景被环。 Associative 意思為關(guān)聯(lián)奋隶,
iOS 下有很多運(yùn)行時特性研侣,這里介紹一下 Associative(關(guān)聯(lián))

這個運(yùn)行時特性矢劲,以及它一些使用場景蒲拉。 Associative

意思為關(guān)聯(lián),能夠?qū)蓚€對象建立一種關(guān)系忽冻。這種關(guān)系是一種 從屬

關(guān)系真朗,也就是說有一個 關(guān)聯(lián)者

和一個 被關(guān)聯(lián)者

。比如說我們可以將一個 NSString

對象關(guān)聯(lián)到一個 UIView

對象上僧诚。這里的 NSString

對象就是 被關(guān)聯(lián)者

, UIView

對象就是 關(guān)聯(lián)者

遮婶。

在 objc/runtime.h

文件中,找到 Associative

相關(guān)的 API 定義湖笨,如下:

/** 
 * 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);

/** 

 * 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);

/** 

 * 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

 */

同時還提供以下枚舉類型的定義:

/**
 * Policies related to associative references.

 * These are options to objc_setAssociatedObject()

 */

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {

    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */

    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 

                                            *   The association is not made atomically. */

    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 

                                            *   The association is not made atomically. */

    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.

                                            *   The association is made atomically. */

    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.

                                            *   The association is made atomically. */

};

API 解析
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

API 為我們提供了將兩個對象建立關(guān)聯(lián)關(guān)系的能力旗扑,參數(shù)解析為:

id object

:指定 關(guān)聯(lián)者

id value

:指定 被關(guān)聯(lián)者

const void *key

: 被關(guān)聯(lián)者

的 KEY 值,方便后續(xù)可以通過該 KEY 值找到該 被關(guān)聯(lián)者

objc_AssociationPolicy policy

: 該參數(shù)作用用來表示 被關(guān)聯(lián)者

的引用策略慈省,也就是內(nèi)存如何進(jìn)行管理的臀防,可通過上述定義的枚舉類型來設(shè)置。

id objc_getAssociatedObject(id object, const void *key)

API 可以通過之前設(shè)置的 KEY 值边败,來獲取 被關(guān)聯(lián)者

對象袱衷,參數(shù)解析如下:

id object

: 關(guān)聯(lián)者

對象

const void *key

:要獲取的 被關(guān)聯(lián)者

的 KEY 值,一個 關(guān)聯(lián)者

可以被關(guān)聯(lián)多對象放闺,一個 關(guān)聯(lián)者

也可以是 被關(guān)聯(lián)這

祟昭,可以通過不同的 KEY 來獲取不同的 被關(guān)聯(lián)者

對象缕坎。

void objc_removeAssociatedObjects(id object)

該 API 可以移除一個 關(guān)聯(lián)者

對象所有的 被關(guān)聯(lián)者

怖侦。當(dāng)需要移除特定的對象時,我們可以使用 objc_setAssociatedObject

方法并指定 id value

參數(shù)對象為空即可谜叹。

以上就是關(guān)于 Associative(關(guān)聯(lián))

特性相關(guān)的 API 介紹了匾寝,下面介紹一下常用的使用場景。

Associative 特性的應(yīng)用
剪切板的信息復(fù)制
在一些時候我們希望用戶可以長按文案信息荷腊,彈出系統(tǒng)的復(fù)制菜單艳悔,提供文案信息的復(fù)制功能,比如長按 UITableViewCell

提供復(fù)制詳情的功能女仰,在 iOS 下我們可以使用 UIMenuController

類來顯示系統(tǒng)菜單猜年,同時為該 UITableViewCell

添加長按手勢,代碼如下:

// 添加長按手勢
UILongPressGestureRecognizer *longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];

[cell addGestureRecognizer:longPressGR];

// 手勢處理

- (void)handleLongPress:(UILongPressGestureRecognizer *) longPressGR {

    UIMenuController *menu = [UIMenuController sharedMenuController];

    [menu setTargetRect:longPressGR.view.frame inView:self.view];

    [menu setMenuVisible:YES animated:YES];

}

// UIMenuController 相關(guān)

- (BOOL)canBecomeFirstResponder {

    return YES;

}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {

    if ( action == @selector(copy:) ) {

        return YES;

    }

    return NO;

}

- (void)copy:(UIMenuController *)menu {

    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

}

從上述代碼可以看到疾忍,復(fù)制信息的邏輯處理是在 copy:

方法中乔外,但是在該方法中,并不能訪問到 cell.detailTextLabel

對象一罩,在該場景中杨幼,我們可以使用 Associative

特性將 UITableViewCell

對象關(guān)聯(lián)到 UIMenuController

對象中,再在 copy:

方法中獲取到被關(guān)聯(lián)對象,從而獲取到 UITableViewCell

對象差购,進(jìn)而訪問 cell.detailTextLabel.text

四瘫。添加代碼如下:

// 處理手勢時,添加如下代碼
objc_setAssociatedObject(menu, @"UITableViewCell", longPressGR.view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

// 處理 copy 時欲逃,添加如下代碼找蜜,來獲取被關(guān)聯(lián)的 UITableViewCell 對象

objc_getAssociatedObject(menu, @"UITableViewCell");

pasteboard.string = cell.detailTextLabel.text;

上述場景中,并不一定非得用 Associative

特性來實(shí)現(xiàn)稳析,還有很多可行的方法锹杈,這里為大家提供一種方法,并且該方法還算是比較優(yōu)雅的迈着。

其他一些應(yīng)用場景
另一個常見的應(yīng)用場景就是竭望,為一個系統(tǒng)類或是一個第三方的類添加一個屬性時,可以結(jié)合 Category

為類添加一個屬性裕菠,當(dāng)然也可以使用繼承來達(dá)到目的咬清。在一些特殊場景下,比如想知道一個系統(tǒng)內(nèi)部對象或者第三方對象是何時被釋放時奴潘,我們可以為該對象關(guān)聯(lián)一個自定義的對象旧烧,并且使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC

來指定內(nèi)存管理策略,當(dāng)關(guān)聯(lián)者被釋放是画髓,被關(guān)聯(lián)者也會跟著被釋放掘剪,這樣可以在我們自定義的對象中,知道感興趣的對象何時被釋放的奈虾。在調(diào)試一些內(nèi)存問題時夺谁,該方法還是蠻有用的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肉微,一起剝皮案震驚了整個濱河市匾鸥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碉纳,老刑警劉巖勿负,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劳曹,居然都是意外死亡奴愉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門铁孵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锭硼,“玉大人,你說我怎么就攤上這事库菲≌送” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳖擒。 經(jīng)常有香客問我溉浙,道長,這世上最難降的妖魔是什么蒋荚? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任戳稽,我火速辦了婚禮,結(jié)果婚禮上期升,老公的妹妹穿的比我還像新娘惊奇。我一直安慰自己,他們只是感情好播赁,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布颂郎。 她就那樣靜靜地躺著,像睡著了一般容为。 火紅的嫁衣襯著肌膚如雪乓序。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天坎背,我揣著相機(jī)與錄音替劈,去河邊找鬼。 笑死得滤,一個胖子當(dāng)著我的面吹牛陨献,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播懂更,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼眨业,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了膜蛔?” 一聲冷哼從身側(cè)響起坛猪,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤脖阵,失蹤者是張志新(化名)和其女友劉穎皂股,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體命黔,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呜呐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悍募。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蘑辑。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坠宴,靈堂內(nèi)的尸體忽然破棺而出洋魂,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布副砍,位于F島的核電站衔肢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏豁翎。R本人自食惡果不足惜角骤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望心剥。 院中可真熱鬧邦尊,春花似錦、人聲如沸优烧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畦娄。三九已至疑苫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纷责,已是汗流浹背捍掺。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留再膳,地道東北人挺勿。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像喂柒,于是被迫代替她去往敵國和親不瓶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

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