OC 中 load 和 initialize 的区别
load:
-
+load
是一个类方法,当程序载入时,在main函数执行之前,带有+load
方法类(Class)或者种类(Category)就会执行+load
方法(每个+load
方法只执行一次),比如:@interface Person : NSObject @end @implementation Person +(void)load { NSLog(@"Person is loaded"); } @end int main(int argc, const char *argv[]) { @autoreleasepool { // insert code here... NSLog(@"main is executed"); } return 0; } // Person is loaded // main is executed
我们可以看到,
Person
类中的+load
方法在main
执行前就被调用了 -
当父类和子类都实现
+load
方法时,父类和子类的+load
方法都会执行(都只执行一次),且父类的+load
方法执行顺序要优先于子类,比如:@interface Person : NSObject @end @interface Father : Person @end @implementation Person +(void)load { NSLog(@"Person is loaded"); } @end @implementation Father +(void)load { NSLog(@"Father is loaded"); } @end // Person is loaded // Father is loaded
我们可以看到
Fahter
是Person
的子类,Person
执行+load
方法后Father
才执行+load
方法 -
当子类未实现
+load
方法时,不会调用父类+load
方法,比如:@implementation Person +(void)load { NSLog(@"Person is loaded"); } @end @implementation Father //+(void)load { // NSLog(@"Father is loaded"); //} @end // Person is loaded
-
当子类实现
+load
方法,而父类没有实现+load
方法时,只调用子类的+load
方法:@implementation Person //+(void)load { // NSLog(@"Person is loaded"); //} @end @implementation Father +(void)load { NSLog(@"Father is loaded"); } @end // Father is loaded
-
类中的
+load
方法执行顺序要优先于种类(Category),种类中+load
方法的执行顺序和Compile Sources中出现的顺序一致:@implementation Person +(void)load { NSLog(@"Person is loaded"); } @end @implementation Person (Category1) +(void)load { NSLog(@"Person Category1 is loaded"); } @end @implementation Person (Category2) +(void)load { NSLog(@"Person Category2 is loaded"); } @end @implementation Person (Category3) +(void)load { NSLog(@"Person Category3 is loaded"); } @end // Person is loaded // Person Category3 is loaded // Person Category1 is loaded // Person Category2 is loaded
可以看到
Person
类的+load
先于所有种类的执行顺序,而Compile Sources中Person
种类出现的顺序是3,1,2,这对应+load
执行的顺序 -
当有多个不同的类的时候,每个类
+load
执行顺序与其在Compile Sources出现的顺序一致 -
+load
是线程安全的,要避免在+load
内堵塞线程。
initialize
-
在类收到第一条消息的时候调用,在main函数开始执行后(因为类方法的调用在
main
中),可能某个类会一直不执行+initialize
,因为这个类可能只是被加载到程序中,而没有被调用(收到消息),每个类只执行+initialize
一次。 -
父类的
+initialize
方法会比子类先执行:@implementation Person +(void)initialize { NSLog(@"Person is initialized"); } @end @implementation Father +(void)initialize { NSLog(@"Father is initialized"); } @end int main(int argc, const char *argv[]) { @autoreleasepool { Father *father = [[Father alloc] init]; Person *person = [[Person alloc] init]; } return 0; } // Person is initialized // Father is initialized
-
当子类未实现
+initialize
方法时,会调用父类+initialize
方法(这样使得同一种+initialize
可能会被执行多次,但这并不与每个类只执行+initialize
一次相矛盾)。@implementation Person +(void)initialize { NSLog(@"Person is initialized"); } @end @implementation Father //+(void)initialize { // NSLog(@"Father is initialized"); //} @end int main(int argc, const char *argv[]) { @autoreleasepool { Father *father = [[Father alloc] init]; } return 0; } // Person is initialized // Person is initialized
-
当有多个Category都实现了
+initialize
方法时,会覆盖类中的方法,+initialize
方法只执行一次(会执行Compile Sources 列表中最后一个Category 的+initialize
方法)@implementation Person +(void)initialize { NSLog(@"Person is initialized"); } @end @implementation Person (Category1) +(void)initialize { NSLog(@"Person Category1 is initialized"); } @end @implementation Person (Category2) +(void)initialize { NSLog(@"Person Category2 is initialized"); } @end @implementation Person (Category3) +(void)initialize { NSLog(@"Person Category3 is initialized"); } @end // Person Category2 is initialized
Compile Sources中Catergory出现的顺序是3,2,1,
+initialize
执行一次,执行的是最后一个(1)。 -
+initiallize
是线程安全的,要避免在+initiallize
内堵塞线程。
总结
方法 | +load |
+initialize |
---|---|---|
执行时间 | 类载入程序时 | 类第一次接受消息时 |
执行次数 | 每个+load 方法只执行一次,不会出现重复执行 |
每个类的+initialize 方法只执行一次,可能会重复执行 |
父类是否优先于子类执行 | 是 | 是 |
子类不实现时,是否调用父类 | 否 | 是(导致父类+initialize 方法执行次数+1) |
子类是否覆盖父类 | 否 | 是 |
Category是否覆盖类 | 否 | 是 |
类的执行是否优先于Category | 是 | 是(因为只执行一次) |
多个Category执行次数 | Category的数量 | 和类一起,总共一次 |
多个Category执行顺序 | Compile Sources中文件出现的顺序 | Compile Sources中文件出现顺序的最后一个 |