iOS开发 load和initialize的介绍

843 阅读3分钟

1.load方法

load方法在这个文件被程序装载时调用。只要是在Compile Sources中出现的文件总是会被装载,这与这个类是否被用到无关,因此load方法总是在main()函数之前调用。 如果一个类实现了load方法,在调用这个方法前会首先调用父类的load方法。而且这个过程是自动完成的,并不需要我们手动实现。 如果一个类没有实现load方法,那么就不会调用它父类的load方法,这一点与正常的类继承和方法调用不一样,需要额外注意一下。

苹果官方文档的解释

Invoked whenever a class or category is added to the Objective-C runtime;
implement this method to perform class-specific behavior upon loading.

这个方法在类被添加进来的时候就会调用,也就是说程序在开始加载期间,这个方法就被调用. load的加载时机: 子类的+load会在父类的+load方法之后执行; 而分类的load则会在主类的load方法之后执行; 不同类之间的load方法调用顺序是不确定的。

当类的加载是耗时或者需要消耗比较多的内存的时候,尽量不要在load方法里面做这些耗时的工作,因为这样会__增加App的启动时间__,降低用户的体验。 由于调用load方法时的环境很不安全,我们应该尽量减少load方法的逻辑。另一个原因是load方法是线程安全的,它内部使用了锁,所以我们应该避免线程阻塞在load方法中。

一个常见的使用场景是在load方法中实现Method Swizzle

2. initialize方法

苹果官方文档的解释

Initializes the class before it receives its first message.
The runtime sends initialize to each class in a program just before the class, or any class that
inherits from it, is sent its first message from within the program. The runtime sends the
initialize message to classes in a thread-safe manner. Superclasses receive this message before
their subclasses. The superclass implementation may be called multiple times if subclasses do not
implement initialize—the runtime will call the inherited implementation—or if subclasses
explicitly call [super initialize]

这个方法会在类的第一个方法调用前被调用。首先会先调用父类的initialize方法,如果子类没有实现initialize方法,那么父类会多次触发这个方法,为了避免这种情况的发生,可以在实现的方法里面添加一个判断:

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

initialize其实可以被认为是延迟加载的方法,类加载的时候并不会执行这个方法,只有当类实例化的时候,或者类的第一个方法被调用的时候才会执行这个方法

3.category中的load和initialize

在category中load方法会等到实现类加载完自身的load方法后再执行category的load方法. initialize则调用最后一个被加载完成的类的initialize的方法.

4 总结

  1. load和initialize方法都会在实例化对象之前调用,以main函数为分水岭,前者在main函数之前调用,后者在之后调用。这两个方法会被自动调用,不能手动调用它们。
  2. load和initialize方法都不用显示的调用父类的方法而是自动调用,即使子类没有initialize方法也会调用父类的方法,而load方法则不会调用父类。
  3. load方法通常用来进行Method Swizzle,initialize方法一般用于初始化全局变量或静态变量。
  4. load和initialize方法内部使用了锁,因此它们是线程安全的。实现时要尽可能保持简单,避免阻塞线程,不要再使用锁。