简介
associatedObject又称关联对象,把一个对象关联到另外一个对象身上,使两者能够产生联系。关联对象的使用场景最多的是给一个分类增加属性。通过objc_setAssociatedObject 和 objc_getAssociatedObject 方法来设置和获取关联对象。通过 objc_removeAssociatedObjects 移除关联对象。
用法
- 设置关联对象API
/**
* Sets an associated value for a given object using a given key and association policy.
*
* @param object The source object for the association. // 要添加关联对象的归属对象
* @param key The key for the association. //用于设置关联对象的key
* @param value The value to associate with the key key for object. Pass nil to clear an existing association. //通过key设置的关联对象的值
* @param policy The policy for the association. For possible values, see “Associative Object Behaviors.” // 设置关联对象类型的策略
*
* @see objc_setAssociatedObject
* @see objc_removeAssociatedObjects
*/
OBJC_EXPORT void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);
- 其中,objc_AssociationPolicy是对设置关联对象类型的描述,有以下可选类型:
- 获取关联对象API
/**
* Returns the value associated with a given object for a given key.
*
* @param object The source object for the association. //关联对象归属的对象
* @param key The key for the association.//用于获取关联对象的key
*
* @return The value associated with the key \e key for \e object.//通过key获取的关联对象的值
*
* @see objc_setAssociatedObject
*/
OBJC_EXPORT id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
OBJC_AVAILABLE(10.6, 3.1, 9.0, 1.0, 2.0);
- 实际使用中,我们会通过以下方式来get/set
static void *asKey = &asKey; // 内存地址
objc_setAssociatedObject(obj, asKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, asKey)
static char asKey;
objc_setAssociatedObject(obj, &asKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, &asKey)
使用属性名作为key
objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @"property");
使用get方法的@selecor作为key
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
实现原理
关联对象并不是存储在被关联对象本身内存中,关联对象是通过AssociationsManager的全局类来做管理。
实现关联对象技术的核心对象有:
- AssociationsManager
- AssociationsHashMap
- ObjectAssociationMap
- ObjcAssociation
存储模型:
答疑
关联对象如何创建weak属性
- 使用中间对象方案。用中间方案弱引用被关联的对象,将中间对象存储起来。
- 使用blcok方案。block弱持有被关联对象,将block存起来,get方法中读取block并执行block,返回弱引用对象
分类能否添加成员变量?如果可以,如何给Category添加成员变量?
- 不能直接给Category添加成员变量,但是可以间接实现Category有成员变量的效果
- 添加关联对象: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)