load 方法,其原型如下:
+(void)load;
对于加入运行期系统中的每个类及分类来说,必定会调用此方法,而且仅调用一次。如果分类和其所属的类都定义了load方法,则先调用类里的,在调用分类的。
load方法的问题在于,执行该方法时,运行期系统处于“脆弱状态”。在执行子类的load方法之前,必定会先执行所有超类的load方法,而如果代码还依赖了其他程序库,那么程序库里相关类的load方法也必定会先执行。然而,根据某个给定的程序库,却无法判断出其中各个类的载入顺序。因此,在load方法中使用其他类是不安全的。如下断代码:
#import <Foundation/Foundation.h>
#import "ClassA.h"
@interface ClassB : NSObject
@end
@implementation ClassB
+(void)load {
NSLog(@"Loading ClassB");
ClassA *object = [ClassA new];
}
@end
此处使用NSLog没有问题,而且相关字符串也会照常记录,因为Foundation框架肯定在运行load方法之前就已经载入系统了。但是,在ClassB的load方法里使用ClassA却不太安全,因为无法确定在执行ClassB的load方法之前,ClassA是不是加载好了。
还有一点需要注意的是,load方法并不想普通方法那样,它并不遵从继承规则。如果某各类本身没有实现load方法,那么不管其各超类是否实现此方法,系统都不会调用。此外,分类和其所属的类里,都可能出现load方法。此时两种实现代码都会调用,类的实现要比分类的实现先调用。
整个应用在执行load方法是都会阻塞,如果load方法中包含繁杂的代码,那么应用程序在执行期间就会变得无响应。不要在里面等待锁,也不要调用可能会加锁的方法。总之,能不做的事情就别做。其真正的用途仅在于调试程序,比如可以在分类里编写此方法,用来判断该分类是否已经正确加载。
想要执行与类相关的初始化操作,还有个办法,就是覆写 +(void)initialize;
该方法会在程序首次用该类之前调用,且只调用一次。其虽与load方法类似,但却有几个非常重要的微妙区别:首先,它是“惰性调用的”,应用程序无须把每个类的initialize方法都执行一遍,这与load方法不同,对于load来说,应用程序必须阻塞等着所有的类的load都执行完,才能继续。其次,运行期系统在执行该方法是,是处于正常状态的,运行期系统也能确保initialize方法一定会在“线程安全的环境”中执行,这就是说,只有执行initialize的那个线程可以操作类或类实例,其他线程都要先阻塞,等着initialize执行完。最后,initialize方法与其他消息一样,如果某个类未实现它,而其超类实现了,那么就会运行超类的实现代码。