一、简介
关联对象的使用一般用于给 Category 添加成员变量。我们知道,分类添加属性只能生成 setter/getter
方法的声明,不能自动生成实现,所以我们需要自己实现两个方法。
1.objc_setAssociatedObject
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
参数 :
id object
: 给哪个对象添加属性 这里要给自己添加属性 用 self
const void *key
: 根据 key
获取关联对象的属性的值 只要是一个指针就好了
id value
: 关联的值 也就是 setter
方法传入的值给属性去保存
objc_AssociationPolicy policy
: 保存策略
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object.
* The association is not made atomically. */
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied.
* The association is not made atomically. */
OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object.
* The association is made atomically. */
OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied.
* The association is made atomically. */
};
用于 setter
方法,例如:
在分类中有这样一个属性:
@property (nonatomic, assign) int weight;
setter
方法 :
- (void)setWeight:(int)weight {
objc_setAssociatedObject(self, @"weight", [NSNumber numberWithInt:weight], OBJC_ASSOCIATION_ASSIGN);
}
注意 int
类型的变量需要转成 NSNumber
类型使用,不然会报错。
2.objc_getAssociatedObject
id objc_getAssociatedObject(id object, const void *key)
用于 getter
方法,例如:
- (int)weight {
return [objc_getAssociatedObject(self, @"weight") intValue];
}
这里需要取出来是一个 NSNumber
类型 所以后面加了 intValue
一般不需要加,在 setter
方法中 weight
关联了一个 NSNumber
对象才需要加。
二、原理
关联对象并不是存储在被关联对象本身的内存中,通过分析底层实现,它存储在由 AssociationsManager
管理的全局统一的一个 AssociationsHashMap
中,关系如下:
从上图可以看出,关联对象的底层实现依赖下面四个核心对象:
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjectionAssociation
它们之间的关系:AssociationsHashMap
里存储着某个对象的关联对象 Map
表,即 ObjectAssociationMap
,这个表存储了多个关联对象,因为在分类里可以给对象添加多个属性,也就要设置多个关联对象, ObjectAssociationMap
中就是我们添加的关联对象,比如 name
,由 ObjectionAssociation
存储值和策略,当我们将关联对象(即 value
值,例如 person.name = nil
)设为 nil
时,AssociationsMap
自动删除这条关联对象;当我们调用 objc_removeAssociatedObjects(id object)
方法时,就是移除某个对象的所有关联对象,即上图中 AssociationHashMap
需要移除对象的关联对象 Map
表;
网友评论