ios底层(一)Category的本质,load,initialize方法的调用顺序

1.Category底层结构,如下

2.使用指令从编译后的c++代码,也可以看出是把在分类中写的方法都赋值给了结构体

将Objective-C代码转换为C\C++代码

xcrun -sdk iphoneos clang  -arch  arm64 -rewrite-objc  OC源文件  -o  输出的CPP文件

如果需要链接其他框架,使用-framework参数。比如-framework UIKit

第一张图中圈的值赋值给了第二张的结构体属性里。

3.分析Category怎么把方法合并到类中的。

是通过dyld装载程序,初始化runtime环境的时候加载到类对象里

直到最后调用到如下方法

上图中圈中2行代码做的事情就是把分类的方法列表加到原始类的方法列表前面。

所以最终会导致,对象调用方法时,先找到分类的方法进行调用。

也就是我们常说的分类方法会“覆盖”原来类的方法的现象,但实际上并不是覆盖,而是因为分类方法被添加在了前面。

因为消息机制isa在查找方法的时候找到就直接调用了,后面不会再管了。

4.我们所写的就分类的方法,如果重名的话,会由编译顺序决定调用哪一个。

还有一点要注意就是写静态库里other linker flags 设置成 -all_load。

5.+load方法的调用

也是在dyld装载程序,初始化runtime环境的时候调用的。所以代码不管是否使用就会调用。

最后调用

而且两个方法内部调用都是直接方法调用,没有使用objc消息机制。

所以写了原类,子类,分类.三个类里面的+load都会依次调用。

6.+initialize方法, 首次使用类的时候只会调用一次

可以看到方法调用采取的是objc消息机制调用,

所以结果为

比如写了原类,子类,分类.三个类里面的+initialize方法,只有原类、分类依次调用。

5和6的调用结果如下图

PS:介于时间有限,本篇只列了一些重点并不算是详细,

这里还有另一篇比较详细,可以参考https://blog.csdn.net/Bolted_snail/article/details/82258597

发布了96 篇原创文章 · 获赞 10 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/feifeiwuxian/article/details/101014847