+load和+initialize

+load和+initialize

+load+initialize 的异同

  1. +load 方法会在 main() 函数之前调用,而 +initialize 是在类第一次使用时才会调用
  2. +load 方法调用优先级:父类>子类>分类,并且不会被覆盖,均会调用
  3. +initialize 调用优先级:分类>父类,父类>子类,父类的分类重写了 +initialize方法会覆盖父类的 +initialize 方法。即:
    • 如果分类和父类均实现了 +initialize,则只有分类的 +initialize 会被调用;
    • 如果父类和子类均实现了 +initialize,第一次引用 子类时,先调用父类的 +initialize,再调用子类的 +initialize
    • 如果父类实现了 +initialize,则第一次引用子类时,会调用两次父类的 +initialize
  4. +load 方法在 main() 函数之前调用,所有的类文件都会加载,分类也会加载
  5. 均无须显式调用 super 方法
load

由于 +load 方法在 App 启动加载的时候调用,此时不能保证所有的类被加载完成。

+load 方法是线程安全的,因为内部有锁,但是也带了一定的性能开销。所以一般会在 +load 方法中实现 Method Swizzle

调用顺序是父类->子类->分类。

多个分类中实现了+load方法,根据Compile Source中的顺序决定。但要遵循调用[ChildClass load]之前,必须先调用其[SuperClass load]方法。

load 方法是直接使用函数指针调用,即走 C 语言函数调用的流程,不是发送消息,并不会走消息转发流程,也就是说如果一个类实现了 load 函数就会调用,如果没有实现也不会调用该类的父类 load 函数。

+initialize 方法

父类->子类,分类会覆盖类,如果子类没有实现 initialize 方法,父类会调用两次

子类实现了 initialize,会先调用父类 initialize,再调用子类 initialize

子类没有实现 initialize,父类 initialize 方法会调用两次

如果先引用父类的实例对象,再引用子类实例对象,则会在引用父类实例对象时调用父类 initialize 方法;当引用子类实例对象时,由于父类的 initialize 方法已经执行,所以此时只调用子类 initialize 方法

如果先引用子类的实例对象,再引用父类的实例对象,则会在引用子类的实例对象时,在调用 initialize 方法前,先调用父类 initialize 方法,再调用子类的 initialize 方法;当引用父类实例对象时,由于在引用子类实例对象时已经调用了 initialzie 方法了,此时不再调用 initialize 方法

+ (void)initialize {
  if (self == [ClassName self]) {
    // ... do the initialization ...
  }
}

或者使用 dispatch_once

load 函数的调用直接是函数指针的调用,而 initialize 函数是消息转发。所以 class 的子类就算没有实现 initialize 函数,也会调用父类的 initialize 函数

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容