底层

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

2020-10-21  本文已影响0人  MonKey_Money

类扩展

@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。
上一篇下一篇

猜你喜欢

热点阅读