iOS中怎么关联对象
创始人
2024-12-19 19:42:45
0次

关联对象源码

存值

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) { _object_set_associative_reference(object, (void *)key, value, policy);}

我们调用此方法的时候,一共传递了四个参数:

id object需要关联的对象void *key对应的keyid value对应的值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. */};

对于四个参数理解完了之后让我们看看它真正的实现函数_object_set_associative_reference

void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) { // retain the new value (if any) outside the lock. ObjcAssociation old_association(0, nil); id new_value = value ? acquireValue(value, policy) : nil; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); disguised_ptr_t disguised_object = DISGUISE(object);//得到对象地址 if (new_value) {  // break any existing association.  AssociationsHashMap::iterator i = associations.find(disguised_object);//首先通过对象的地址获取对象的hashmap  if (i != associations.end()) {//判断是否已经存在,已经存在  // secondary table exists  ObjectAssociationMap *refs = i->second;//取值,对应的map  ObjectAssociationMap::iterator j = refs->find(key);//通过key查找  if (j != refs->end()) {//如果已经存在   old_association = j->second;//取到原来老的值,以便后边对其释放   j->second = ObjcAssociation(policy, new_value);//存储新的值  } else {//不存在   (*refs)[key] = ObjcAssociation(policy, new_value);  }  } else {//如果不存在,创建一个  // create the new association (first time).  ObjectAssociationMap *refs = new ObjectAssociationMap;  associations[disguised_object] = refs;  (*refs)[key] = ObjcAssociation(policy, new_value);  object->setHasAssociatedObjects();  } } else {//不存在则创建一个  // setting the association to nil breaks the association.  AssociationsHashMap::iterator i = associations.find(disguised_object);  if (i != associations.end()) {  ObjectAssociationMap *refs = i->second;  ObjectAssociationMap::iterator j = refs->find(key);  if (j != refs->end()) {   old_association = j->second;   refs->erase(j);  }  } } } // release the old value (outside of the lock). if (old_association.hasValue()) ReleaseValue()(old_association);}

通过以上代码我们可以看出其实关联对象在存储的时候在,生成了一个AssociationsManager单例对象,所以应用中所有的管理对象都存储于此AssociationsManager中。

具体存储的实现是借助了C++的关联容器unordered_map实现的。具体可以参看代码中我加的注释。

整个过程就是通过object对象的地址存储了一个类似hashmap的东西;取到此hashmap,然后通过键值对的方式将我们需要存储的值存储到此hashmap中,这个过程中如果有旧值,则最后会将旧值就行释放

取值

取值的过程其实就比较简单了,就相当于从一个hashmap中取值

id objc_getAssociatedObject(id object, const void *key) { return _object_get_associative_reference(object, (void *)key);}

id _object_get_associative_reference(id object, void *key) { id value = nil; uintptr_t policy = OBJC_ASSOCIATION_ASSIGN; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); disguised_ptr_t disguised_object = DISGUISE(object); AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) {  ObjectAssociationMap *refs = i->second;  ObjectAssociationMap::iterator j = refs->find(key);  if (j != refs->end()) {  ObjcAssociation &entry = j->second;  value = entry.value();  policy = entry.policy();  if (policy & OBJC_ASSOCIATION_GETTER_RETAIN) {   objc_retain(value);  }  } } } if (value && (policy & OBJC_ASSOCIATION_GETTER_AUTORELEASE)) { objc_autorelease(value); } return value;}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...