頭文件:html
#import <objc/runtime.h>
Objective-C 開發者習慣於警戒運行時的東西,理由是運行時改變了運行在它上面代碼的實際結構。ios
另外一方面,<objc/runtime.h>
的功能就是爲應用或框架增長更強大的新特性,是其餘的方式沒法git
實現的。同時它也可能破壞原來代碼的邏輯結構,一切與之可能進行的交互,都將有可怕的反作用。github
給咱們帶來極大的惶恐,所以,咱們稱之爲浮士德,也是NSHipster讀者常常被所要求的科目之一:緩存
關聯的對象。關聯的對象或關聯的引用,他們本來是Objective-C的2.0運行時的新特性,在OS Xapp
雪豹中介紹(可在iOS 4的)的功能。它在運行時鍵值允許對象爲任意值,這個條目是在框架
<objc/ runtime.h>聲明的,有如下三個C函數:異步
objc_setAssociatedObject
objc_getAssociatedObject
objc_removeAssociatedObjects
爲何會這樣有用嗎?它容許開發人員在分類中自定義屬性,拓展的類,彌補Objective-C的這個缺陷。ide
NSObject+AssociatedObject.h
@interface NSObject (AssociatedObject) @property (nonatomic, strong) id associatedObject; @end
NSObject+AssociatedObject.m @implementation NSObject (AssociatedObject) @dynamic associatedObject; - (void)setAssociatedObject:(id)object { objc_setAssociatedObject(self, @selector(associatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (id)associatedObject { return objc_getAssociatedObject(self, @selector(associatedObject)); }
人們一般的建議是使用靜態字符,或者更好的是指針。這基本上保證一個任意的值是固定的、惟一的,函數
並且僅限於getter和setter方法中使用:
static char kAssociatedObjectKey; objc_getAssociatedObject(self, &kAssociatedObjectKey);
然而,一個更簡單的解決方案存在:只使用一個SEL。
值能夠根據由枚舉類型objc_AssociationPolicy定義的行爲相關聯的物體上
Behavior | @property Equivalent | Description |
---|---|---|
OBJC_ASSOCIATION_ASSIGN | @property (assign) or @property (unsafe_unretained) | Specifies a weak reference to the associated object. |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | @property (nonatomic, strong) | Specifies a strong reference to the associated object, and that the association is not made atomically. |
OBJC_ASSOCIATION_COPY_NONATOMIC | @property (nonatomic, copy) | Specifies that the associated object is copied, and that the association is not made atomically. |
OBJC_ASSOCIATION_RETAIN | @property (atomic, strong) | Specifies a strong reference to the associated object, and that the association is made atomically. |
OBJC_ASSOCIATION_COPY | @property (atomic, copy) | Specifies that the associated object is copied, and that the association is made atomically. |
有人可能控制不住地各類誘惑,在他們某些關聯的對象時調用objc_removeAssociatedObjects()。
可是,如文檔中描述的,你基本沒有將有機會親自調用它: 此函數的主要目的是能夠很容易將對象返回
到「原始狀態」,你不該該使用這個函數從對象通常移除關聯,由於它也消除了其餘對象可能已添加到該
對象關聯。一般狀況下,你應該使用objc_setAssociatedObject 設置nil,以清除關聯。
相關聯的對象應被看做是不得已的方法,而不是尋找問題的解決方案(說真的,類自己真的不該該在工具鏈的頂端開始)。 如同任何聰明的把戲,駭客攻擊,或解決方法,通常都會積極尋求應用的場合,尤爲是瞭解以後,這是人的一種天然的傾向 。盡你所能地理解和欣賞時,這是正確的解決方案,保存本身被輕蔑地問:「爲何要以神的名義」,而後你決定去解決。
相關代碼: