美文网首页
Category底层实现原理

Category底层实现原理

作者: 是超超呀 | 来源:发表于2021-04-28 16:45 被阅读0次

    category的实现原理

    编译之后,category在内存中的结构体为 category_t ,编译器会把该类的所有分类依次编译为 category_t 类型的结构体,结构体中包含对象方法列表、类方法列表、协议列表、属性列表等,编译时,并不进行结构体合并,在内存中是独立存在的。

    通过runtime的动态特性,在程序运行时,将分类结构体中的对象方法、协议、属性 合并进类对象中,将类方法合并进元类对象中,“合并”,实际上是在内存中,对数据进行内存移动memmove 和 memcpy

    memmove 是根据传入的数据内存大小,从哪开始移动,中间是有一个判断的,是向左挪动还是向右挪动(可以保证数据的完整性);而 memcpy 不判断,它是从最小的内存开始逐一复制移动,将分类中的数据插入到原来数据前面

    进行内存移动的时候,memmove 不会造成内存覆盖;从新的地方进行内存移动的时候,使用 memcpy 比较合适,因为它不需要管数据是否会内存覆盖

    category的加载处理过程

    1.通过RunTime加载某个类的所有Category数据

    2.把所有的category方法,属性,协议数据合并到一个大数组中,后面参与的category数据,会被加到数组前面

    3.将合并的分类数据(方法,属性,协议),插入到原来数据的前面

    Category 和 Extension(匿名分类) 的区别

    Class-Extension 在编译阶段,它的数据就已经加载到了类信息中(类 对象、元类对象),而Class-Category是在运行时,才将数据合并到类信息中。

    Category 中load方法什么时候调用?load方法能继承吗?

    load方法会在runtime加载类和分类的时候调用。

    调用顺序:1.先调用类的+load,按照编译先后顺序调用(先编译,先调用)调用子类的+load之前会先调用父类的+load;2.再调用分类的+load,按照编译先后顺序调用(先编译,先调用)

    load能继承,但是一般情况下不主动去调用load方法,都是让系统自己去调用。

    load,initialize的方法区别是什么?它们在Category中的调用顺序?以及出现继承时他们之间的调用过程?

    调用方式

    load,根据函数地址直接调用(IMP)。initialize,通过objc_msgSend调用,类第一次接收到消息的时候调用

    调用时机

    load,runtime加载类、分类的时候调用(只调用一次)。initialize,类第一次收到消息的时候调用,每个类只会调用一次(父类的+initialize 可能会被调用多次)

    调用顺序

    load,先调用类的+load(先编译先调用,调用子类load之前先调用父类的load),再调用分类的+load。initialize,先调用父类的+initialize,再调用自己的+initialize

    继承出现时,调用子类load之前先调用父类的load,先调用父类的+initialize,再调用自己的+initialize

    相关文章

      网友评论

          本文标题:Category底层实现原理

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