oc 分类方法、+(void)load、+(void)initialize方法调用分析

分类同名方法调用原理

1、分类方法在类被加载时由runtime插入到类对象/元类对象的methodList的前面

2、多个分类时采用倒序遍历,把方法汇总到一个addedList数组中,所以最后参与编译的分类方法在addedList的最前面

3、把2中的addedList的方法整体插入到类对象的methodList的最前面

4、当上层在调用某个方法时通过objc_msgSend方法查找方法列表,找到方法入口地址,完成调用过程

5、所以分类和本类有同名方法时只会调用最后一个参与编译的分类方法

+ (void)load;

1、load方法在类加载时由runtime找到load方法的函数指针,通过函数指针直接调用

2、当分类和本类同时实现load方法时,所有的load方法都会调用

3、先调用所有本类的load方法,再调用分类的load方法

4、调用某个类的load的方法前会递归调用其父类的load,即先调用父类的,最后调用自己的

5、多个分类的load方法按照先编译的先调用原则

+ (void)initialize;

1、当第一次给某个类发送消息时调用,且一个类只初始化一次

2、initialize方法是通过objc_msgSend方法在元类的方法列表中查找函数,实现调用的

3、当分类和本类同时实现该方法时,只调用分类的initialize方法(因为分类的方法在methodList的最前面)

4、当初始化某个类时会先递归初始化其父类的initialize(如果父类在子类之前已经初始化,则该父类不再初始化)

5、由于是通过objc_msgSend调用,所以当初始化子类时如果子类没有实现initialize,则会向上查找实现了initialize方法的父类,然后调用该方法。该设计会带来一个父类的initialize方法被多次调用的现象,但是本质还是每个类只初始化一次,由于子类没有实现而调用父类的initialize方法,其本质是利用父类的initialize方法初始化子类。

你可能感兴趣的:(oc 分类方法、+(void)load、+(void)initialize方法调用分析)