iOS-Category管理对象的原理

上次我们说到 iOS-Category添加成员变量 是通过 objc_setAssociatedObjectobjc_getAssociatedObject来实现的,我们一起来探究下这两个方法的底层实现。

我们可以通过下载开源的runtime的代码,来查看一下底层的实现方法。Runtime的开源代码

【_object_set_associative_reference】

01.jpg

【_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类中所有的关联对象。

推荐阅读更多精彩内容