# 10、在既有类中使用关联对象存放自定义数据

可以给某对象关联许多其他对象，这些对象通过“键”来区分。存储对象值的时候，可以指明“存储策略”（storage policy），用以维护相应的“内存管理语义”。策略有名为`objc_AssociationPolicy`的枚举所定义：

| `objc_AssociationPolicy`关联类型         | 等效的@property属性   |
| ------------------------------------ | ---------------- |
| OBJC\_ASSOCIATION\_ASSIGN            | assign           |
| OBJC\_ASSOCIATION\_RETAIN\_NONATOMIC | nonatomic，retain |
| OBJC\_ASSOCIATION\_COPY\_NONATOMIC   | nonatomic，copy   |
| OBJC\_ASSOCIATION\_RETAIN            | retain           |
| OBJC\_ASSOCIATION\_COPY              | copy             |

​ 以下方法可以管理关联对象：

* `void objc_setAssociatedObject(id object, void* key, id value, objc_AssociationPolicy policy)`此方法以给定的键和策略为某对象设置关联对象值
* `id objc_getAssociatedObject(id object, void* key)`此方法根据给定的键从某对象中获取相应的关联对象值
* `void objc_removeAssociatedObject(id object)`此方法移除指定对象的全部关联对象

  ​ 可以把某对象想像成`NSDictionary`，把关联到该对象的值理解为字典中的条目，存储关联对象的值就相当于在字典对象调用`setObject:valueforKey:`和`objectForKey:`方法。然而两者之间有个重要差别：**设置关联对象时用的键（key）时一个“不透明的指针”（opaque pointer）。如果在两个键上调用`isEqual:`方法返回YES，那么字典人为二者相等；而在设置关联对象值时，若向令两个键匹配到同一个字，则二则必须是完全相同的指针才行。鉴于此，在设置关联对象值时，通常使用静态全局变量做键。**

关联对象用法举例：

​ 可以看这篇文章（[iOS\_理解“属性”（property）这一概念](https://blog.csdn.net/margaret_mo/article/details/109268073)）的 `@dynamic`（二-2）：在Category中为类添加属性。

要点：

* 可以通过“关联对象”机制来把两个对象连起来
* 定义关联对象时可指定内存管理语义，用以模仿定义属性时所采用的“拥有关系”与“非拥有关系”
* 只有在其他做法不可行时才应选用关联对象，因为这种做法通常会引入难于查找的bug
