【引】objective-c,5:Associated Objects 的原理

时间:2024-04-09 19:33:27

参考博客:

http://blog.leichunfeng.com/blog/2015/06/26/objective-c-associated-objects-implementation-principle/

从之前实例的内存结构,cls的对象结构,以及category的实现原理知道,可以通过 Category 给一个现有的类添加属性,但是却不能添加实例变量。

可以通过 Associated Objects 来弥补这一不足,以下主要介绍Associated Objects的实现原理。

同时要关注3个问题:

  1,关联对象被存储在什么地方,是不是存放在被关联对象本身的内存中

  2,关联对象的五种关联策略

  3,关联对象的生命周期是怎样的,什么时候被释放,什么时候被移除

1,关联对象的五种策略:

  关联函数相关的有3个函数:

【引】objective-c,5:Associated Objects 的原理

setAssociatedObject中的key值,一般可以用:

  1,static char CHARKEY 和 &CHARKEY;

  2,static void *kAssociatedObjectKey = &kAssociatedObjectKey;

  3,对于配对出现的setter和getter,可以灵活应用_cmd。但是其他地方这样用,对于绑定变量的获取不好用。

绑定的五种策略:

【引】objective-c,5:Associated Objects 的原理

2,关联对象的生命周期:

  会根据绑定策略的不同而不同。

  objc_association_assign的关联对象,在自身所在的runloop结束后,就会被释放。

  其他强持有的绑定方式,在会在被关联对象(宿主对象,比如绑定给self)被释放后,调用_object_remove_assocations,把宿主对象的所有关联对象移除,最终,强指针指向的那些对象被释放。

3,实现机制:

  1,其实系统全局维护了一个无序的哈希表AssociationsHashMap,维护了对象地址到ObjectAssociationMap的映射。也就是说,每一个对象都维护这自己的一个ObjectAssociationMap。

  2,ObjectAssociationMap维护了从key到ObjcAssociation的映射。也就是关联记录。

  3,至于ObjcAssociation,表示一个具体的关联结构,主要包括两个实例变量,_policy 表示关联策略,_value 表示关联对象。

 所以setAssociatedObject的原理就可以清楚,

  1,首先根据对象的地址,在AssociationsHashMap中获取ObjectAssociationMap。如果ObjectAssociationMap不存在则创建。

  2,根据传入的key值在ObjectAssociationMap中创建一个ObjcAssociation。如果原本的对应关系已经有,则会释放原有的对应关系,再创建新的对应。

 getAssociatedObject的原理也可以清楚:

  1,首先根据对象的地址,在AssociationsHashMap中获取ObjectAssociationMap。如果能找到,则2,否则3

  2,如果找到,则进一步根据 key 在 ObjectAssociationMap对象中查找这个 key 所对应的关联结构 ObjcAssociation 。如果能找到,则返回 ObjcAssociation 对象的 value 值。

  3,否则返回nil。

所以一开始第1个问题:

  1,关联对象被存储在什么地方,是不是存放在被关联对象本身的内存中

  不是的。一个实例的内存结构是已经定下的。关联对象和宿主对象的存储不是直接相关的。而是在一张全局哈希表里维护的。

ps,

  关于5种策略。OBJC_ASSOCIATION_RETAIN_NONATOMIC等强持有策略,可以让宿主对象持有关联对象。而使用assign策略,关联对象是不会被持有的。