关联对象

2019-05-13  本文已影响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的常见用法

objc_setAssociatedObject(obj,MyKey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
 objc_getAssociatedObject(obj,MyKey)
objc_setAssociatedObject(obj,&MyKey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,&MyKey)
objc_setAssociatedObject(obj,@"property",value,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj,@"property");
objc_setAssociatedObject(obj,@selector(getter),value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,@selector(getter))

objc_AssociationPolicy

image

关联对象原理

关联对象核心对象

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

小结

上一篇 下一篇

猜你喜欢

热点阅读