前言
iOS 中我们给分类进行添加属性成员变量使用的 runtime 的 Associated API ,但是我们对原理了解过少,下面说下 关联对象的本质和原理。
1. 关联对象的本质
-
关联对象并不是存储在被关联对象本身内存中,跟原本的对象没有内存关系,关联对象存储在全局的统一的一个AssociationsManager中。
-
设置关联对象为nil,就相当于是移除关联对象。
2. 关联的原理
- 设置关联对象的原理,是系统通过 AssociationsManager 管理多个hash map,通过 object_set_associative 设置相应的 key 和 value存储到 hash map 中,在取出的时候再通过对应的 key 取出对应的 value。
- 如果使用字典也可以实现相应类的功能,使分类也可以拥有属性。
3. 原理具体
首先系统中有一个全局AssociationsManager, 里面有个AssociationsHashMap哈希表,哈希表中的key是对象的内存地址,value是ObjectAssociationMap,也是一个哈希表,其中key是我们设置关联对象所设置的key,value是ObjcAssociation,里面存放着关联对象设置的值和内存管理的策略。
void objc_setAssociatedObject(id object, const void * key,id value, objc_AssociationPolicy policy)为例,首先会通过AssociationsManager获取AssociationsHashMap,然后以object的内存地址为key,从AssociationsHashMap中取出ObjectAssociationMap,若没有,则新创建一个ObjectAssociationMap,然后通过key获取旧值,以及通过key和policy生成新值ObjcAssociation(policy, new_value),把新值存放到ObjectAssociationMap中,若新值不为nil,并且内存管理策略为retain,则会对新值进行一次retain,若新值为nil,则会删除旧值,若旧值不为空并且内存管理的策略是retain,则对旧值进行一次release