Category底层实现原理

时间:2021-6-12 作者:qvyue

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

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。