load 和 initialize

2018-11-01  本文已影响0人  马小峰MXF

参考文档:

iOS底层原理总结 - Category的本质 - 掘金

Objective-C 深入理解 +load 和 +initialize - iOS - 掘金

问题汇总:

1、Category 中有 load 方法吗?load 方法是什么时候调用的?load 方法能继承吗?

Category 中有 load 方法,load 方法在程序启动装载类信息的时候就会调用。load 方法可以继承。调用子类的 load 方法之前,会先调用父类的 load 方法。

2、load、initialize 的区别,以及它们在 category 重写的时候的调用的次序。

1)区别在于调用方式和调用时刻

i:调用方式:load 是根据函数地址直接调用,initialize 是通过 objc_msgSend 调用

ii:调用时刻:load 是 runtime 加载类、分类的时候调用(只会调用1次),initialize 是类第一次接收到消息的时候调用,每一个类只会 initialize 一次(父类的 initialize 方法可能会被调用多次

2)调用顺序:先调用类的 load 方法,先编译那个类,就先调用 load。在调用 load 之前会先调用父类的 load 方法。分类中 load 方法不会覆盖本类的 load 方法。initialize 先初始化父类,之后再初始化子类。如果子类没有实现 +initialize,会调用父类的 +initialize(所以父类的 +initialize 可能会被调用多次),如果分类实现了 +initialize,就覆盖类本身的 +initialize 调用。

load

load方法在装载类信息的时候就会调用。

通过源码我们发现是优先调用类的 load 方法,之后调用分类的 load 方法。

我们通过代码验证一下: 我们添加 Student 继承 Presen 类,并添加 Student+Test 分类,分别重写只 +load 方法,其他什么都不做通过打印发现:

确实是优先调用类的 load 方法之后调用分类的 load 方法,不过调用类的 load 方法之前会保证其父类已经调用过 load 方法。

initialize

之后我们为 Preson、Student 、Student+Test 添加 initialize 方法。

我们知道当类第一次接收到消息时,就会调用 initialize,相当于第一次使用类的时候就会调用initialize 方法。调用子类的 initialize 之前,会先保证调用父类的 initialize 方法。如果之前已经调用过 initialize,就不会再调用 initialize 方法了。当分类重写 initialize 方法时会先调用分类的方法。首先我们来看一下 initialize 的源码。

上图中我们发现,initialize 是通过消息发送机制调用的,消息发送机制通过 isa 指针找到对应的方法与实现,因此先找到分类方法中的实现,会优先调用分类方法中的实现。

我们再来看一下 load 方法的调用源码:

我们看到 load 方法中直接拿到 load 方法的内存地址直接调用方法,不再是通过消息发送机制调用。

我们可以看到分类中也是通过直接拿到 load 方法的地址进行调用。因此正如我们之前试验的一样,分类中重写 load 方法,并不会优先调用分类的 load 方法。

上一篇下一篇

猜你喜欢

热点阅读