关联对象使用 为分类添加属性。(只是为属性添加了getter/setter方法,并没有生成带下划线的实例变量)。
1 2 3 4 5 6 7 8 9 10 11 12 13 void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) // 1. 通过 key : value 的形式给对象 object 设置关联属性 void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy); // 2. 通过 key 获取关联的属性 object id objc_getAssociatedObject(id object, const void *key); // 3. 移除对象所关联的属性 void objc_removeAssociatedObjects(id object);
id object:被关联的对象
const void *key:关联的key,要求唯一
id value:给被关联的对象设置的值
objc_AssociationPolicy policy:内存管理的策略
关联对象源码解读
预备知识 在正式开始看这个源码之前,我们先来看看实现关联对象中涉及到的几个结构:
AssociationsManager 1 2 3 4 5 6 7 8 9 10 11 12 13 class AssociationsManager { static spinlock_t _lock; static AssociationsHashMap *_map; // 这个_ map 里边存储关联列表 public: AssociationsManager() { _lock.lock(); } ~AssociationsManager() { _lock.unlock(); } AssociationsHashMap &associations() { if (_map == NULL) _map = new AssociationsHashMap(); return *_map; } };
AssociationsManager 主要就是维护了一个 AssociationsHashMap,当第一次获取时,如果没有则会新建。并且在 AssociationsManager 所在作用域内,还有一个自旋锁 spinlock_t,防止在多线程情况下对 AssociationsHashMap 出现问题。
AssociationsHashMap 1 2 3 4 5 class AssociationsHashMap : public unordered_map<disguised_ptr_t, ObjectAssociationMap *, DisguisedPointerHash, DisguisedPointerEqual, AssociationsHashMapAllocator> { public: void *operator new(size_t n) { return ::malloc(n); } void operator delete(void *ptr) { ::free(ptr); } };
key: object经过特殊处理成为key
value: ObjectAssociationMap
ObjectAssociationMap 1 2 3 4 5 class ObjectAssociationMap : public std::map<void *, ObjcAssociation, ObjectPointerLess, ObjectAssociationMapAllocator> { public: void *operator new(size_t n) { return ::malloc(n); } void operator delete(void *ptr) { ::free(ptr); } };
key: 设置关联对象时,传入的关联的 key(经过转换)
value:ObjcAssociation
ObjcAssociation 1 2 3 4 5 6 7 8 9 10 11 12 class ObjcAssociation { uintptr_t _policy; id _value; public: ObjcAssociation(uintptr_t policy, id value) : _policy(policy), _value(value) {} ObjcAssociation() : _policy(0), _value(nil) {} uintptr_t policy() const { return _policy; } id value() const { return _value; } bool hasValue() { return _value != nil; } };
设置关联对象时设置的内存管理策略
设置关联对象时传入的value
下边是这个 AssociationsManager 包含的层级关系:
objc_setAssociatedObject 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 ///给某个对象添加关联属性 void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) { _object_set_associative_reference(object, (void *)key, value, policy); } // 通过对策略的判断返回不同的值 static id acquireValue(id value, uintptr_t policy) { switch (policy & 0xFF) { case OBJC_ASSOCIATION_SETTER_RETAIN: return objc_retain(value); case OBJC_ASSOCIATION_SETTER_COPY: return ((id(*)(id, SEL))objc_msgSend)(value, SEL_copy); } return value; } void _object_set_associative_reference(id object, void *key, id value, uintptr_t policy) { // 初始化一个 old_association 对象,用于在 AssociationsManager 锁的内部,暂时持有原有值 ObjcAssociation old_association(0, nil); id new_value = value ? acquireValue(value, policy) : nil; { // 取 manager,并取出其中的 AssociationsHashMap AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); // 将传入的 object 做一次转换,作为 AssociationsHashMap 的 key 值 disguised_ptr_t disguised_object = DISGUISE(object); // 传入设置的 value 有值的情况 if (new_value) { // 根据 AssociationsHashMap 的 disguised_object 值,生成正向迭代器(ObjectAssociationMap) AssociationsHashMap::iterator i = associations.find(disguised_object); // 迭代器中有值 if (i != associations.end()) { // i->second,找到 AssociationsHashMap 中 disguised_object 对应的 ObjectAssociationMap ObjectAssociationMap *refs = i->second; // 根据函数传入的 key 值,生成正向迭代器(ObjcAssociation) ObjectAssociationMap::iterator j = refs->find(key); // 迭代器中有值 if (j != refs->end()) { // 找到 ObjectAssociationMap 中 key 对应的 ObjcAssociation // 先用 old_association 保存原来的 ObjcAssociation // 再根据传入的 new_value 及 policy 生成新的 ObjcAssociation 对象 // key: 新生成的 ObjcAssociation 对象 old_association = j->second; j->second = ObjcAssociation(policy, new_value); } else { // 根据传入的 new_value 及 policy 生成新的 ObjcAssociation 对象 // key: 新生成的 ObjcAssociation 对象 (*refs)[key] = ObjcAssociation(policy, new_value); } } else { // 以 obejct 为 key,未找到 ObjectAssociationMap // 则新建一个 ObjectAssociationMap // disguised_object: ObjectAssociationMap ObjectAssociationMap *refs = new ObjectAssociationMap; associations[disguised_object] = refs; // 根据传入的 new_value 及 policy 生成新的 ObjcAssociation 对象 // key: 新生成的 ObjcAssociation 对象 (*refs)[key] = ObjcAssociation(policy, new_value); object->setHasAssociatedObjects(); } } // 传入的 new_value 为 nil 的情况 else { // 根据 AssociationsHashMap 的 disguised_object 值,生成正向迭代器(ObjectAssociationMap) AssociationsHashMap::iterator i = associations.find(disguised_object); // 迭代器中有值 if (i != associations.end()) { // i->second,找到 AssociationsHashMap 中 disguised_object 对应的 ObjectAssociationMap ObjectAssociationMap *refs = i->second; // 根据函数传入的 key 值,生成正向迭代器(ObjcAssociation) ObjectAssociationMap::iterator j = refs->find(key); if (j != refs->end()) { // 找到 ObjectAssociationMap 中 key 对应的 ObjcAssociation // 先用 old_association 保存原来的 ObjcAssociation // 将迭代器中的数据清除,即清除原 ObjcAssociation 对象 old_association = j->second; refs->erase(j); } } } } // 释放 old_association 对象 if (old_association.hasValue()) Rele aseValue()(old_association); } struct ReleaseValue { void operator() (ObjcAssociation &association) { releaseValue(association.value(), association.policy()); } };
objc_getAssociatedObject 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 ///获取某个对象的关联属性 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) { // 初始化 value 及 policy,承载取出 ObjcAssociation 实例对象的值, id value = nil; uintptr_t policy = OBJC_ASSOCIATION_ASSIGN; { AssociationsManager manager; // 获取 AssociationsHashMap AssociationsHashMap &associations(manager.associations()); // 转换 object 作为 AssociationsHashMap 的 key 值 disguised_ptr_t disguised_object = DISGUISE(object); // 根据 AssociationsHashMap 的 disguised_object 值,生成正向迭代器(ObjectAssociationMap) AssociationsHashMap::iterator i = associations.find(disguised_object); // 迭代器中有值 if (i != associations.end()) { // i->second,找到 AssociationsHashMap 中 disguised_object 对应的 ObjectAssociationMap ObjectAssociationMap *refs = i->second; // 根据函数传入的 key 值,生成正向迭代器(ObjcAssociation) ObjectAssociationMap::iterator j = refs->find(key); // 迭代器中有值 if (j != refs->end()) { // 找到 ObjectAssociationMap 中 key 对应的 ObjcAssociation // 将 ObjcAssociation 实例对象的 value 及 policy 赋值给开始定义的局部变量 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; }
objc_removeAssociatedObjects 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ///移除对象所有的关联属性 void objc_removeAssociatedObjects(id object) void _object_remove_assocations(id object) { vector< ObjcAssociation,ObjcAllocator<ObjcAssociation> > elements; { AssociationsManager manager; AssociationsHashMap &associations(manager.associations()); if (associations.size() == 0) return; disguised_ptr_t disguised_object = DISGUISE(object); AssociationsHashMap::iterator i = associations.find(disguised_object); if (i != associations.end()) { // copy all of the associations that need to be removed. ObjectAssociationMap *refs = i->second; for (ObjectAssociationMap::iterator j = refs->begin(), end = refs->end(); j != end; ++j) { elements.push_back(j->second); } // remove the secondary table. delete refs; associations.erase(i); } } // the calls to releaseValue() happen outside of the lock. for_each(elements.begin(), elements.end(), ReleaseValue()); }
关联对象如何实现weak属性 设置关联对象的方法中,传入的 policy 枚举值如下:
1 2 3 4 5 6 7 8 9 10 11 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. */ };
要实现 weak ,说白了就是要做到两点:
引用计数器不变;
对象销毁后自动设置为 nil。
而在 runtime 所提供的枚举中,OBJC_ASSOCIATION_ASSIGN 就已经做到了第一点,我们只需要实现第二点即可。第二点是要在对象销毁后,将 weak 引用设置为 nil ,所以我们要捕获这个对象销毁的时机,或者接收这个对象销毁的事件。在 ARC 中,对象销毁时机其实就是 dealloc 方法调用的时机,我们可以在这个方法里将这个 weak 引用设置为 nil。
SomeClass+WeakProperty –> ObjectValue –> DeallocBlock –> SomeClass+WeakProperty
当设置 SomeClass+WeakProperty 值时,我们再动态地为 ObjectValue 添加一个 DeallocBlock,在这个 Block 中,我们将 SomeClass+WeakProperty 的属性置为 nil。然后,在 ObjectValue 的 dealloc 方法中,执行自己持有的 DeallocBlock。
// 待后续更新代码