美文网首页
关联对象

关联对象

作者: 英雄出少年 | 来源:发表于2019-05-13 18:19 被阅读0次

    如何实现给分类“添加成员变量”?

    默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。可以通过关联对象来间接实现

    尝试过程

    1、添加全局变量可以保存值,但是是全局性的会覆盖以前的值

    
    @implementation TGPerson (Test)
    
    intweight_;
    
    - (void)setWeight:(int)weight {
        weight_= weight;
    }
    
    - (int)weight {
        return weight_;
    }
    
    @end
    
    

    2、 添加全局字典,线程安全

    
    @implementation TGPerson (Test)
    
    NSMutableDictionary *weights_;
    + (void)load {
        weights_ = [NSMutableDictionary dictionary];
    }
    
    - (void)setWeight:(int)weight {
        NSString *key = [NSString stringWithFormat:@"%p", self];
        weights_[key] =@(weight);
    }
    
    - (int)weight {
        NSString *key = [NSString stringWithFormat:@"%p", self];
        return [weights_[key] intValue];
    }
    
    @end
    
    

    2、关联对象

    • 设置关联对象
    void objc_setAssociatedObject(id object,const void * key,  id value,objc_AssociationPolicy policy)
    
    • 获取关联对象

    id objc_getAssociatedObject(id object,const void * key)

    • 移除所有的关联对象

    void objc_removeAssociatedObjects(id object)

    key的常见用法

    • static void *MyKey = &MyKey;(用自己的地址值)
    objc_setAssociatedObject(obj,MyKey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
     objc_getAssociatedObject(obj,MyKey)
    
    • static const char MyKey;
    objc_setAssociatedObject(obj,&MyKey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj,&MyKey)
    
    • 使用属性名作为key
    objc_setAssociatedObject(obj,@"property",value,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    objc_getAssociatedObject(obj,@"property");
    
    • 使用get方法的@selecor作为key
    objc_setAssociatedObject(obj,@selector(getter),value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    objc_getAssociatedObject(obj,@selector(getter))
    

    objc_AssociationPolicy

    image

    关联对象原理

    关联对象核心对象

    • AssociationsManager

    • AssociationsHashMap

    • ObjectAssociationMap

    • ObjcAssociation (存放 value,policy,关联对象的值存在这个对象里)

    image image image image

    源码解读

    objc-references.mm

    classAssociationsManager {
        static AssociationsHashMap *_map;
    public:
        AssociationsManager()  { AssociationsManagerLock.lock(); }
        ~AssociationsManager()  { AssociationsManagerLock.unlock(); }
        AssociationsHashMap&associations() {
            if(_map==NULL)
                _map = new AssociationsHashMap();
            return*_map;
        }
    };
    
    
    //objc_removeAssociatedObjects 移除关联对象
        classObjcAssociation {
            uintptr_t_policy;
            id_value;
        public:
            ObjcAssociation(uintptr_tpolicy,idvalue) :_policy(policy),_value(value) {}
            ObjcAssociation() :_policy(0),_value(nil) {}
            uintptr_t policy() const { return _policy; }
            idvalue()const{return_value; }
            boolhasValue() {return_value!=nil; }
        };
    
    void_object_remove_assocations(idobject) {
        vector< ObjcAssociation,ObjcAllocator<ObjcAssociation> > elements;
        {
            AssociationsManager manager;
           AssociationsHashMap&associations(manager.associations());
            if(associations.size() ==0)return;
            disguised_ptr_tdisguised_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);
                }
                deleterefs;
                associations.erase(i);
            }
        }
        for_each(elements.begin(), elements.end(), ReleaseValue());
    }
    
    
    image

    小结

    • 关联对象并不是存储在被关联对象本身内存中

    • 关联对象存储在全局的统一的一个AssociationsManager中

    • 设置关联对象为nil,就相当于是移除关联对象

    • 对关联的object没有引用,操作的是地址,object销毁 关联对象也会移除

    相关文章

      网友评论

          本文标题:关联对象

          本文链接:https://www.haomeiwen.com/subject/mwbraqtx.html