load 和 initialize
参考文档:
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 方法。