load方法在类被加载前会有且只调用一次,不会走objc_msgSend的流程,所以分类或者当前类的load方法不会被覆盖,都会被调用,当然分类中的方法覆盖其实不是真真意义上的覆盖,而是将分类的方法放在了方法列表最前面,由于消息发送机制通过isa找方法,找到后就不会继续找下去了。
load方法执行顺序,从objc-os.mm文件中的_objc_init开始找
从上图可以看出call_class_loads()方法先调用完所有类的load方法,再calss_category_loads()调用所有分类的load方法
而且在调用所有类的方法时,是从i=0开始的,也就是说从最前面的类开始调用,由于自己尝试过,最先编译的会被最新调用,所以类的调用就是跟编译顺序有关,至于父类的,再看下面的源码
这里是构建类的列表,可以看出这里是个递归调用,说白了就是先将当前类的父类、父类的父类。。先加入到类的列表中,再将自己加入到类列表中,也就是说load方法先调用当前类的祖父(如果有而且之前没有被调用)、父类(如果有而且之前没有被调用),最后才是自己的load方法
再看分类
直接找到分类的load方法进行调用,也是跟编译顺序有关,不管编译顺序是分类在前还是在后,都会先将类的load方法走完了再依次调用分类的
网上有个面试题说load方法可以继承吗?
如果严格来说,load方法是可以被继承的,但一般不会主动去调用load方法,如果主动去调用load方法,则会走objc_msgSend消息发送机制,结果就是分类的load的方法被优先调用,而这里说的load方法是直接找到函数imp进行调用,没有走objc_msgSend的流程
网友评论