+load方法

网上有很多这样的面试题,之前也有人问过我。但是一直也没有时间进行详细的探索,并做记录。

最近正好拿出来进行研究。下面会用到源码objc4-781,在官网上下载最新的。

我们先来看一下+load方法,我们新建几个类和分类,类和分类里面写上+load方法,并做打印

main函数里面什么也不写,头文件也不需要引入,我们运行一下,看一下会有什么效果。

运行之后的结果

我们可以看到这里已经调用了上面定义的类和分类的+load方法,我们什么都没有做,为什么会调用呢?

我们想要分析为什么,还需要从源码进行分析。

首先我们要找到runtime的入口,入口是在objc-os.mm文件下面的_objc_init方法


_objc_init方法

_dyld_objc_notify_register里面load_images点进去之后下面有个 call_load_methods()方法点进去

call_load_methods()

上面是先调用类方法里面的+load方法,下面是调用分类里面的+load方法。从上面的打印结果我们也可以看出是先调用类的在调用分类的。看一下调用方法里面的实现。


call_class_loads()

loadable_classes是非懒加载类+load 方法的数组。是loadable_class结构体,里面包含Class和IMP两个变量。所以classes里面也是同样的,之后用for循环遍历直接调用load方法。

但是loadable_classes数组里面的东西还有一些细节需要注意。就是里面存储结构体的顺序什么样的。因为顺序不同调用的结果也就不一样。到底在哪里看呢?

上面我们有一个load_images方法,里面有一句prepare_load_methods((const headerType *)mh);代码,点进去

prepare_load_methods

我们可以看到classlist里面放的是所有不是懒加载的类,通过for循环调用schedule_class_load这个方法。

schedule_class_load

add_class_to_loadable_list这个方法里面就是把有+load的发放入到loadable_classes数组中。但是上面可以看出使用了递归,

是对传入进来类的父类进行遍历。所以加入loadable_classes数组放把父类的+load方法先放到里面。所以在下面调用的时候是先调用父类的+load。

除了继承关系以外,其他的顺序是按照编译的顺序进行调用。

分类原理类似,但是不会像类一样先调用父类的load,分类只是单纯的按照编译顺序进行调用。

prepare_load_methods

这里也可以看出直接就调用添加数组里面。

总结一下+load方法

1、+load方法会在runtime加载类和分类时调用

2、调用的顺序有几个注意点(先调用类的load方法,如果类有继承关系先调用父类的load方法---类才有的,分类没有,其他情况就是按照编译的顺序进行调用,先编译先调用)

你可能感兴趣的:(+load方法)