load和initialize经常被提及,但实际编码中其实使用不多,一个知识即使当时了解的再清楚,一直不使用,也会慢慢忘记,就好像我现在想不起来高中物理的很多公式一样。
说起这些总要说起原理,其实原理是什么呢,就是苹果在runtime的源码中怎样去调用这两个方法的。细节很多,挑出关键流程其实也只能是知其然不知其所以然,只能是知道了这么做,却不知道为什么这么做。优秀的源码总是经过多次测试多次修改多次优化的。
站在路的终点,我们可能很难想起走在途中的心路历程。还是需要慢慢摸索,认真沉淀才行。
放个总结,方便回忆。
维度 | load | initialize |
---|---|---|
是否需要调用Super | 不需要 | 不需要 |
调用时机 | 类或者category加载到runtime时由系统自动调用 在main函数之前 | 在类或者子类在第一次收到消息时调用(类消息或者实例消息)在main函数之后 |
调用方式 | 直接通过函数的内存地址调用的,不走msg_send,不走OC消息转发,每个类的load方法都是独立的 | 走OC消息转发, msg_send |
调用次数 | 只会调用一次 | 1. 可能会调用多次,如果子类没有实现该方法,则子类在第一次收到消息时会调用父类的方法。2.如果在子类收到消息前,父类没有收到过消息,那么会先调用父类的initialize方法之后再调用子类的initialize方法。 |
调用顺序 | 父类-子类-category 。1.所有的类都加载完之后才会调用所有的category。 2.不同的类的load执行顺序跟编译顺序有关,可以在Target -> Build Phases -> Compile Sources 中调整顺序。但所有的category都是在所有的类的load都执行完之后,才会调的。 3.多个类的多个category或者一个类的不同category的load方法的顺序同样跟编译顺序有关,可以在compiles source中调整。 | 父类-子类(如果category有实现,会只调用category中的实现;父类的category会覆盖父类的实现,子类的category会覆盖子类的category实现) |
使用 | 一般用来实现 Method Swizzle | 一般用来初始化全局变量 或者 静态变量 |
网友评论