iOS 关联对象笔记

方法

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存储,所有对象的关联内容都在同一个容器中,这个全局容器的数据结构类似下图。


1304277-5d2fe26987ca4b54.png

注意:为什么不放在本类中,由于类的内存布局已预先设置,关联对象添加的属性或者变量不能放在原有类结构上,找一个全局容器以key value方式存储。

如何清除一个关联对象的值?

如图,把value设置为nil,走的就是图中else分支,就可以擦除。

1304277-124675260760e81f.png

注意:你可以会在刚开始接触对象关联时想要尝试去调用 objc_removeAssociatedObjects() 来进行删除操作,但如文档中所述,你不应该自己手动调用这个函数。

苹果文档解释如下:
此函数的主要目的是在“初试状态”时方便地返回一个对象。你不应该用这个函数来删除对象的属性,因为可能会导致其他客户对其添加的属性也被移除了。规范的方法是:调用 objc_setAssociatedObject 方法并传入一个 nil 值来清除一个关联。

关联对象本质的总结:

1304277-227b71cb07468364.png

根据图中由下往上,
1)首先,传入的value(“Hello”)和policy(OBJC_ASSOCIATION_COPY_NONATOMIC)封装成ObjcAssociation这样一个结构;
2)通过ObjcAssociation和selector的key 建立的一个映射结构ObjcAssociationMap;
3)再把2)中的ObjcAssociationMap作为全局容器AssociatonsHashMap的一个value,对应的key为DISGIUISE(obj)。

参考链接

关联对象相关面试问题
关联对象 AssociatedObject 完全解析

猜你喜欢

转载自blog.csdn.net/weixin_33965305/article/details/87246902