06·iOS 面试题·Category 中有 load 方法吗?
前言
面对题目的三连问,只要我们了解 Category 的加载时机,类中的 load 方法是如何调用的,就可以清晰的回答这三个疑问。
对于 Category 相关实现原理,可以直接看:02·iOS 面试题·Category 的实现原理,以及 Category 为什么只能加方法不能加属性? ,这里就不重复叙述了,下面就直接正面回答题目问题了:
Category 中是有 load 方法的
在运行时时期,会将 Category 中的实例方法列表、协议列表、属性列表添加到主类中,并且不会对 load 方法做特殊处理,故 load 方法跟其它方法一样,被插到主类中。
每个类都可以自己实现 load 方法的。
+ load 方法是在运行时时期调用的
在运行时时期,将 Category 中的实例方法列表、协议列表、属性列表添加到主类中后,会递归调用所有类的 load 方法,递归调用确保以下几点:
- 父类的 load 方法先调用
- 主类中的 load 方法先调用,分类中的 load 方法后调用
- 分类之间的 load 方法调用顺序,看文件编译的顺序
+ load 方法特殊之处
在运行时时期,循环调用所有类的 +load 方法。直接使用函数内存地址的方式 (*load_method)(cls, SEL_load);
而不是使用发送消息 objc_msgSend
的方式。
这个就会导致:类、父类和分类中的 +load 方法的实现是被区别对待的。也就是说如果子类没有实现 +load 方法,那么当它被加载时 runtime 是不会去调用父类的 +load 方法的。同理,当一个类和它的分类都实现了 +load 方法时,两个方法都会被调用。
总结
对于题目的问题,只要我们掌握 Category 相关实现原理,就可以轻松的回答上来;
简单总结下:Category 是在运行时时期将方法、协议、属性插入到主类中,对于 load 方法并没有做特殊操作,所以 load 方法跟其它方法一样,会 “覆盖” 主类的方法;
同时在运行时时期,又会递归调用 load 方法,而且是通过函数指针直接调用的,没有走消息转发的机制,这就导致只要类实现了 load 方法就会被调用。