1
+ (void)load

对于加入运行期系统中的每个类(class)及分类(category)来说,必定会调用此方法,而且仅调用一次。当被包含类或分类的程序库载入系统时,就会执行此方法,而这通常就是指应用程序启动的时候,若程序是为 iOS 平台设计的,则肯定会在此时执行。Mac OS X 应用程序更自由一些,他们可以使用「动态加载」之类的特性,等应用程序启动好再去加载程序库。如果分类和其所属的类都定义了 load 方法,则先调用类里面的,在调用分类里的

load 方法的问题在于,执行该方法时,运行期系统处于「脆弱状态」。在执行子类的 load 方法之前,必定会执行所有超类的 load 方法,而如果代码还依赖了其他程序库,那么程序库里相关类的 load 方法也必定会先执行。然而,根据某个给定的程序库,却无法判断出其中各个类的载入顺序。因此,在 load 方法中使用其他类是不安全的。

有个重要的事情需注意,那就是 load 方法并不像普通方法那样,它并不遵从那套集成规则。如果某个类本身没实现 load 方法,那么不管其他各级超类是否实现此方法,系统都不会调用。此外,分类和其所属的类里,都可能出现 load 方法。此时两种实现代码都会调用,类的实现要比分类的实现先执行

而且 load 方法务必实现得精简一些,也就是要尽量减少其所执行的操作,因为整个应用程序在执行 load 方法时都会阻塞。如果 load 方法中包含繁杂的代码,那么应用程序在执行期间就会变得无响应。不要在里面等待锁,也不要调用可能会加锁的方法。总之,能不做的事情就别做。实际上,凡是想通过 load 在类加载之前执行某些任务的,基本都做得不太对。其真正用途仅在于调试程序,比如可以在分类里编写此方法,用来判断该分类是否已经正确载入系统中。

—— 摘自《Effective Objective-C 2.0》

1
+ (void)initialize

对于每个类来说,该方法会在程序首次用该类之前调用,且只调用一次。它是由运行期系统来调用的,绝不应该通过代码直接调用。其虽与 load 相似,但却有几个非常重要的微妙区别。首先,它是「惰性调用」的,也就是说,只有当程序用到了相关的类时,才会调用。因此,如果某各类一直都没有使用,那么其 initialize 方法就一直不会运行。这也就等于说,应用程序无须先将某个类的 initialize 都执行一遍,这与 load 方法不同,对于 load 来说,应用程序必须阻塞并等着所有类的 load 都执行完,才能继续。

此方法和 load 还有个区别,就是运行期系统在执行该方法时,是处于正常状态的,因此,从运行期系统完整度上来讲,此时可以安全使用并调用任意类中的任意方法。而且,运行期系统也能确保 initialize 方法一定会在「线程安全」的环境中执行,这就是说,只有执行 initialize 的那个线程可以操作类或类实例。其他线程都要先阻塞,等着 initialize 执行完。
最后一个区别是:initialize 方法与其他消息一样,如果某个类未实现它,而其超类实现了,那么就会运行超类的实现代码

—— 摘自《Effective Objective-C 2.0》

参考链接