关联对象底层结构

关联对象的方法

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);

了解了这三个方法,我们需要先记住添加关联对象方法的四个参数,分别是objectkeyvaluepolicy,这四个参数的含义分别是:
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 {
    public:
        void *operator new(size_t n) { return ::malloc(n); }
        void operator delete(void *ptr) { ::free(ptr); }
    };

其中我们需要关心的参数有两个分别是disguised_ptr_tAssociationsManager,其中disguised_ptr_t是我们设置关联对象时的那个object,并且这个objectAssociationsManager用作为key,ObjectAssociationMap是存储的哪个对象,并作为value,这个对象里面可能有多个关联对象。

ObjectAssociationMap的结构

 class ObjectAssociationMap : public std::map {
    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);
关联对象结构.png

你可能感兴趣的:(关联对象底层结构)