上次我們說到 iOS-Category添加成員變量 是通過
objc_setAssociatedObject
和objc_getAssociatedObject
來實現(xiàn)的次坡,我們一起來探究下這兩個方法的底層實現(xiàn)飞袋。
我們可以通過下載開源的runtime的代碼限佩,來查看一下底層的實現(xiàn)方法答毫。Runtime的開源代碼
【_object_set_associative_reference】
【_object_get_associative_reference】
通過上圖的方法可以看到幻馁,實現(xiàn)關(guān)聯(lián)對象技術(shù)的核心對象為一下四個:
① AssociationsManager
② AssociationsHashMap
③ ObjectAssociationMap
④ ObjcAssociation
這四個的關(guān)系如下所示:
class AssociationsManager {
...
AssociationsHashMap &get() {
return _mapStorage.get();
}
...
};
typedef DenseMap<DisguisedPtr<objc_object>, ObjectAssociationMap> AssociationsHashMap;
typedef DenseMap<const void *, ObjcAssociation> ObjectAssociationMap;
class ObjcAssociation {
uintptr_t _policy;
id _value;
};
/**
① id object --相當于Person對象
② const void *key 對應(yīng)ObjectAssociationMap
③ id value --ObjcAssociation中的value
④ uintptr_t policy--ObjcAssociation中的policy
*/
_object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
由上圖可知绞吁,關(guān)聯(lián)對象并不是放在原來對象里面哗脖,而是通過runtime自己維護了一個Map糊肠。
【總結(jié)】:
- 關(guān)聯(lián)對象并不是存儲在被關(guān)聯(lián)對象本身內(nèi)存中闸盔;
- 關(guān)聯(lián)對象存儲在全局統(tǒng)一的一個AssociationsManager中
- 設(shè)置關(guān)聯(lián)對象為nil ,就相當于移除當前關(guān)聯(lián)對象悯辙;
- 調(diào)用
objc_removeAssociatedObjects(<#id _Nonnull object#>)
方法,移除Person類中所有的關(guān)聯(lián)對象迎吵。