美文网首页iOS 底层分析
iOS关联对象的底层实现

iOS关联对象的底层实现

作者: Good_Citizen | 来源:发表于2019-11-22 17:43 被阅读0次

    分类不能直接添加成员变量,可以通过关联对象间接达到添加成员变量的效果,不能添加成员变量是由于分类的底层结构体是这样的

    分类里面有实例方法列表、类方法列表、协议列表、实例属性列表、类属性列表,没有成员变量列表,类似ivars的变量,所以分类中不能添加成员变量,下面通过代码看下

    上图可以看出,给类WPPerson添加了一个分类,然后定义了一个name属性,在getter方法中使用_name成员变量是报错的

    其实也可以手动实现有成员变量的假象,让外部使用起来没有什么感觉,做法是定义一个全局字典,将外部调用setter方法传进来的数据保存在字典中,大家可以自己尝试下。

    下面说下关联对象的使用,关联对象主要是通过调用两个方法来实现

    先说下这几个参数:

    参数1:需要关联的对象,传self

    参数2:key,这是一个void*,所以传一个地址进去

    参数3:value,外部传入的值

    参数4:关联存储策略,和我们平时修饰属性时一样,copy,strong,assign,nonatomic。。。

    用法很简单,由于在分类中添加属性,系统只会生成该属性的setter和getter方法的申明,所以需要自己写实现

    这样外部在使用时和在类里面定义的属性就没有什么区别,但底层实现和直接在类里面定义的属性是不一样的,下面通过源码看下关联对象的底层实现

    主要实现在_object_set_associative_reference方法里面,先说下这几个类的关系

    AssociationsManager结构 AssociationsHashMap结构 ObjectAssociationMap结构 ObjectAssociation结构

    AssociationsManager:管理者

    AssociationsHashMap:里面存储着所有关联对象的信息,一个键值就是一个关联对象的信息(WPPerson、WPCat。。。)

    AssociationsHashMap:里面存储着当前WPPerson关联对象的所有关联属性信息,一个键值就是一个属性信息(name、age。。)

    ObjectAssociation:里面存储着当前属性的关联策略以及具体的值

    这样一层层的就能找到对应的关联信息,比如我们想获取WPPerson的name属性的值时,先找到AssociationsManager里面的AssociationsHashMap,再通过WPPerson的实例作为key从AssociationsHashMap找到对应的value也就是AssociationsHashMap,再通过name的key也就是@selector(name)最为key从AssociationsHashMap中找到ObjectAssociation,这样就能拿到name属性的具体值了

    下面给源码添加了注释

    清除关联对象只需要调用方法的时候将value传入nil即可

    所以关联对象底层其实是用一个全局的hashMap将self与所谓的成员变量保存起来,并不是存在类对象或者元类对象里面

    相关文章

      网友评论

        本文标题:iOS关联对象的底层实现

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