相关Class或Struct
AssociationsManager:全局唯一的关联对象管理者。
AssociationsHashMap:全局关联对象的hashMap,{DISGUISE(object):ObjectAssociationMap}
ObjectAssociationMap:某个对象的关联对象hashMap。{key:ObjcAssociation}
ObjcAssociation:关联对象的封装。{policy:0,value:"text"}
数据格式
{
"0x4565412387": {
"@selector(text)": {
"policy": "copy",
"value": "text"
},
"@selector(color)": {
"policy": "retain",
"value": "color"
}
},
"0x1535342987": {
"@selector(text)": {
"policy": "copy",
"value": "text"
}
}
}
}
源码(主干)
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) {
_object_set_associative_reference(object, (void *)key, value, policy);
}
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);
// 传入的value不为空
if (new_value) {
// break any existing association.
//在AssociationsHashMap迭代查找ObjectAssociationMap
//在AssociationsHashMap找到了ObjectAssociationMap
AssociationsHashMap::iterator i = associations.find(disguised_object);
if (i != associations.end()) {
// secondary table exists
//AssociationsHashMap中是以disguised_object为key,ObjectAssociationMap为value
//i->second表示取value
ObjectAssociationMap *refs = i->second;
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
//ObjcAssociation对象原本有值,重新赋值。
old_association = j->second;
j->second = ObjcAssociation(policy, new_value);
} else {
//ObjcAssociation对象原本没值,赋新值。
(*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 { //传入value == nil
// setting the association to nil breaks the association.
//先以对象为key,在全局AssociationsHashMap查找
AssociationsHashMap::iterator i = associations.find(disguised_object);
//如果在AssociationsHashMap找到了
if (i != associations.end()) {
ObjectAssociationMap *refs = i->second;
//ObjectAssociationMap中是以传入的key为key,以ObjcAssociation为value
ObjectAssociationMap::iterator j = refs->find(key);
if (j != refs->end()) {
old_association = j->second;
//如果传入value == nil,将会把传入的key,value键值对擦除。
refs->erase(j);
}
}
}
}
// release the old value (outside of the lock).
if (old_association.hasValue()) ReleaseValue()(old_association);
}