iOS 基础知识之关联对象

简介

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是对设置关联对象类型的描述,有以下可选类型:
    image.png
  • 获取关联对象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
image.png

存储模型:


image.png

答疑

关联对象如何创建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)

你可能感兴趣的:(iOS 基础知识之关联对象)