方法
void objc_setAssociatedObject(id object, const void *key, id value,
objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void *key);
void objc_removeAssociatedObjects(id object);
三个方法的作用分别是:
- 以键值对形式添加关联对象
- 根据 key 获取关联对象
- 移除所有关联对象
例子
下面AFN的一个例子
- (AFImageDownloadReceipt *)af_activeImageDownloadReceipt {
return (AFImageDownloadReceipt *)objc_getAssociatedObject(self, @selector(af_activeImageDownloadReceipt));
}
- (void)af_setActiveImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt {
objc_setAssociatedObject(self, @selector(af_activeImageDownloadReceipt), imageDownloadReceipt, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
注意:对于key的写法有很多种参考下面链接,个人比较喜欢上述的写法
存储位置
关联对象由AssociationsManager管理并在AssociationsHashMap存储,所有对象的关联内容都在同一个容器中,这个全局容器的数据结构类似下图。
注意:为什么不放在本类中,由于类的内存布局已预先设置,关联对象添加的属性或者变量不能放在原有类结构上,找一个全局容器以key value方式存储。
如何清除一个关联对象的值?
如图,把value设置为nil,走的就是图中else分支,就可以擦除。
注意:你可以会在刚开始接触对象关联时想要尝试去调用 objc_removeAssociatedObjects() 来进行删除操作,但如文档中所述,你不应该自己手动调用这个函数。
苹果文档解释如下:
此函数的主要目的是在“初试状态”时方便地返回一个对象。你不应该用这个函数来删除对象的属性,因为可能会导致其他客户对其添加的属性也被移除了。规范的方法是:调用 objc_setAssociatedObject 方法并传入一个 nil 值来清除一个关联。
关联对象本质的总结:
根据图中由下往上,
1)首先,传入的value(“Hello”)和policy(OBJC_ASSOCIATION_COPY_NONATOMIC)封装成ObjcAssociation这样一个结构;
2)通过ObjcAssociation和selector的key 建立的一个映射结构ObjcAssociationMap;
3)再把2)中的ObjcAssociationMap作为全局容器AssociatonsHashMap的一个value,对应的key为DISGIUISE(obj)。
网友评论