美文网首页
关联属性

关联属性

作者: 小冰山口 | 来源:发表于2024-03-10 13:12 被阅读0次
    思考, 如何实现给分类"添加成员变量"?

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

    关联对象提供了以下API

    • 添加关联对象
    
    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 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_getAssociatedObject(self, _cmd)
    

    一般用第四种: 使用get方法的@selecor作为key

    再来看一下: objc_AssociationPolicy
    图片来源小码哥

    我们看下objc_setAssociatedObject底层究竟做了些什么:

    image.png

    直接调用了_object_set_associative_reference:

    image.png

    所以, 这个数据存储的流程就是:
    运行时全局维护了一个AssociationsManager管理类, 那么这个管理类里又有一个AssociationsHashMap
    这个AssociationsHashMap是通过object为key存储数据的, 也就是说, 一个对象对应一条数据, 那么每个关联的对象都对应一条数据.
    这条数据就又是一个hashMap, 即: ObjectAssociationMap
    那么ObjectAssociationMap里面又是什么呢?
    ObjectAssociationMap以你传入的keykey, 值是由你传入的policyvalue组成的结构体为值

    如下图所示:


    图片来源小码哥

    如果设置valuenil, 会移除掉这个key吗?

    image.png
    如果通过key找到了, 就会直接删除这个value, 如果整个关联对象中已经不存在需要关联的值, 那就会把整个关联对象都删掉.

    我们再来看看objc_getAssociatedObject

    image.png

    内部调用了_object_get_associative_reference

    image.png

    可以很清楚的看到逻辑:

    • 先通过object, 找到associations这个hashmap里的值, 也是一个hashmap, 叫做ObjectAssociationMap

    • 再通过key找到refs里的值, 就是association, 里面存储了policyvalue值, 最后返回的是association里的autoreleaseReturnedValue值.

    而移除所有关联对象, objc_removeAssociatedObjects 就是根据objectkey, 找到对应的hashMap, 然后再删掉, 如下图所示:

    image.png

    相关文章

      网友评论

          本文标题:关联属性

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