美文网首页底层
iOS-OC底层14:关联对象和类扩展

iOS-OC底层14:关联对象和类扩展

作者: MonKey_Money | 来源:发表于2020-10-21 15:38 被阅读0次

    类扩展

    @interface LGPerson ()
    
    @property (nonatomic, copy) NSString *ext_name;
    
    - (void)ext_instanceMethod;
    - (void)ext_classMethod;
    
    @end
    

    1.可以说成是特殊的分类,也称作匿名分类
    分类的声明

    @interface LGPerson (Cate)
    
    @end
    

    2.可以给类添加成员属性
    3.可以给类添加方法。

    总结:类扩展帮助类声明属性,方法和成员变量,一般在m文件中声明,由于在m文件中声明对调用者不可见 所以是私有的。声明的属性会自动生成getter和setter方法并实现

    类别(分类)

    1.专门用于给类添加新的方法

    2.不能给类添加成员变量,添加了成员变量,也无法取到

    给分类添加成员变量会报错实例变量不能放在类别中

    3.可以通过runtime给分类添加属性

    4.分类中用@ property定义变量,只会生成变量的getter和setter方法的声明,不能生成方法实现和带下划线的成员变量。

    可以通过clang -rewrite-objc main.m -o outFile查看
    给分类添加属性,系统会对setter 和getter方法声明,我们可以访问,然后编译不会报错,但是运行会报错。我们通过关联实现setter和getter方法

    @property (nonatomic, copy) NSString *cate_name;
    
    - (void)setCate_name:(NSString *)cate_name{
        /**
         1: 对象
         2: 标识符
         3: value
         4: 策略
         */
        objc_setAssociatedObject(self, "cate_name", cate_name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    - (void)setCate_good:(NSString *)cate_good {
        objc_setAssociatedObject(self, "cate_good", cate_good, OBJC_ASSOCIATION_COPY_NONATOMIC);
    
    }
    

    关联对象

    查看源码看调用过程


    setAssociateddrawio.png

    在_object_set_associative_reference中我们查看类之间的关系


    Associations.png
    void
    _object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
    {
        DisguisedPtr<objc_object> disguised{(objc_object *)object};
        ObjcAssociation association{policy, value};
        association.acquireValue();
        {
            AssociationsManager manager;
            AssociationsHashMap &associations(manager.get());
            if (value) {
                auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});
                if (refs_result.second) {
                    object->setHasAssociatedObjects();
                }
                auto &refs = refs_result.first->second;
                auto result = refs.try_emplace(key, std::move(association));
                if (!result.second) {
                    association.swap(result.first->second);
                    printf("%s",__func__);
                }
            } 
        }
        // release the old value (outside of the lock).
        association.releaseHeldValue();
    }
    

    1.DisguisedPtr:封装object对象,用来查询map的key值
    2.ObjcAssociation:封装策略和值
    3.AssociationsManager:里面包含一个静态map,用来处理关联对象的表
    4.AssociationsHashMap:一个map,初始化传入的是AssociationsManager对象中的静态表,
    5.association.acquireValue();使用传入的策略对value值进行引用计算的处理

    1. auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});从静态map中通过object取出一个包含两个数据的结构
    2. if (refs_result.second) 如果是对象的第一次关联,则对对象的isa关联变量设值为true
      8.refs.try_emplace(key, std::move(association)); 通过object 找到静态表(MAP)中对应的表(MAP),在通过传入的key进行设值value。

    相关文章

      网友评论

        本文标题:iOS-OC底层14:关联对象和类扩展

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