关联对象的方法
runtime给我们提供了三个关于关联对象的方法,如下。点击查看如何添加关联对象
//设置关联对象的方法
OBJC_EXPORT void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy);
//获取关联对象的方法
OBJC_EXPORT id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key);
//删除关联对象的方法
OBJC_EXPORT void
objc_removeAssociatedObjects(id _Nonnull object);
了解了这三个方法,我们需要先记住添加关联对象方法的四个参数,分别是object、key、value、policy,这四个参数的含义分别是:
1.object源对象(一般用self)
2.key关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性,这里咱们填写的是&nameKey)
3.value关联的对象(name)
4.policy一个关联策略
关联对象的核心对象
首先我们要知道的是关联对象并不是存储在被关联对象本身内存中,它是统一存储在一个全局的AssociationsManager中,而实现关联对象技术的核心对象有四个,分别是:
- AssociationsManager
- AssociationsHashMap
- ObjectAssociationMap
- ObjcAssociation
AssociationsManager的结构
class AssociationsManager {
// associative references: object pointer -> PtrPtrHashMap.
static AssociationsHashMap *_map;
public:
AssociationsManager() { AssociationsManagerLock.lock(); }
~AssociationsManager() { AssociationsManagerLock.unlock(); }
AssociationsHashMap &associations() {
if (_map == NULL)
_map = new AssociationsHashMap();
return *_map;
}
};
其中static AssociationsHashMap *_map;是我们真正要关心的内容,public里面的内容是一个锁和如果没有AssociationsHashMap对象就新创建一个并返回其地址。
AssociationsHashMap的结构
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); }
};
其中我们需要关心的参数有两个分别是disguised_ptr_t和AssociationsManager,其中disguised_ptr_t是我们设置关联对象时的那个object,并且这个object在AssociationsManager用作为key,ObjectAssociationMap是存储的哪个对象,并作为value,这个对象里面可能有多个关联对象。
ObjectAssociationMap的结构
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); }
};
这里面我们需要关心的参数有两个分别是void *和ObjcAssociation,其中void *是我们设置关联对象时传递的参数key,这个key也是我们某一个关联对象的key,而ObjcAssociation就是我们最终关联的那个对象了。
ObjcAssociation的结构
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; }
};
这里面我们需要关心的参数有两个分别是uintptr_t _policy;和id _value;,其中_value是我们关联对象的值,比如我们关联的是字符串,这个就是那个字符串,而_policy就是关联的策略。
以上结构中,public:里面都是该结构的一些方法,不必过度关心,下面为用一个图来表示整个结构的关系,我把设置关联对象的那个方法再次贴到下面,为了方便看,我会做好分行,且不写返回值void
objc_setAssociatedObject(id _Nonnull object,
const void * _Nonnull key,
id _Nullable value,
objc_AssociationPolicy policy);
