上次我们说到 iOS-Category添加成员变量 是通过
objc_setAssociatedObject
和objc_getAssociatedObject
来实现的,我们一起来探究下这两个方法的底层实现。
我们可以通过下载开源的runtime的代码,来查看一下底层的实现方法。Runtime的开源代码
【_object_set_associative_reference】
【_object_get_associative_reference】
02.jpg
通过上图的方法可以看到,实现关联对象技术的核心对象为一下四个:
① AssociationsManager
② AssociationsHashMap
③ ObjectAssociationMap
④ ObjcAssociation
这四个的关系如下所示:
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;
};
03.jpg
04.jpg
/**
① id object --相当于Person对象
② const void *key 对应ObjectAssociationMap
③ id value --ObjcAssociation中的value
④ uintptr_t policy--ObjcAssociation中的policy
*/
_object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
由上图可知,关联对象并不是放在原来对象里面,而是通过runtime自己维护了一个Map。
【总结】:
- 关联对象并不是存储在被关联对象本身内存中;
- 关联对象存储在全局统一的一个AssociationsManager中
- 设置关联对象为nil ,就相当于移除当前关联对象;
- 调用
objc_removeAssociatedObjects(<#id _Nonnull object#>)
方法,移除Person类中所有的关联对象。
网友评论