关联对象的底层原理

258 阅读2分钟

关联对象简介:

关联对象就是可以把一个key、value和你的对象给关联起来。 实现关联对象技术的核心对象有:
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation

关联对象的底层是一个ObjcOssociationManager,内部会持有一个ObjcOssociationsHashMap,HashMap的key是你传入的object对象,值是 ObjcOssociationHashMap,这个map的key又是你传入的key,值是ObjcOssociation,ObjcOssociation就存储着外部传入的value和policy。

屏幕快照 2021-08-09 下午10.15.41.png

核心API:
添加关联对象objc_setAssociatedObject:(id object、key、value、policy)- 可以是类对象或实例对象都行、
获取关联对象objc_getAssociatedObject(id object, key)、
删除所有关联对象objc_removeAssociatedObjects:(id object) \

- (void)removeAssociatedObjects { 
// 移除所有关联对象 
objc_removeAssociatedObjects(self); 
}

移除object的所有关联key。objc_setAssociatedObject(object, key, nil, policy) 设置nil,
移除object关联的某个key。 可以使用@selector(key) 获取get方法的 selector 的形式作为key。@selector() 是全局唯一的。

总结:

关联对象并不是存储在被关联对象本身内存中,而是存储在全局统一的一个ObjcAssociationManager中,如果设置关联对象的值为nil,就相当于移除了关联对象。

objc_AssociationPolicy policy 参数: 属性以什么形式保存的策略

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, // 指定一个弱引用相关联的对象 
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 指定相关对象的强引用,非原子性 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 指定相关的对象被复制,非原子性 
OBJC_ASSOCIATION_RETAIN = 01401, // 指定相关对象的强引用,原子性 
OBJC_ASSOCIATION_COPY = 01403 // 指定相关的对象被复制,原子性 };

其中只有RETAIN和COPY而为什么没有weak呢?
weak修饰的属性,当没有拥有对象之后就会被销毁,并且指针置位nil,那么在对象销毁之后,但是在map中依然存在着object对应的AssociationsHashMap,但是因为object地址已经被置位nil,会造成坏地址访问而无法根据object对象的地址转化为disguised_object了。

关联对象的是用场景: