做为 NSObject 类中的 2 个方法 initialize 和 load 一直被咱们所熟知,可是又没有具体去深刻的了解,今天结合 Apple 官方文档,咱们来深刻了解一下 initialize 和 load 方法 。objective-c
看文档能够得知 initialize 方法的做用是在 class 收到第一个消息以前初始化 class。安全
Initializes the class before it receives its first message.
+ (void)initialize;
复制代码
接下来咱们用代码来探究 initialize 这个方法,咱们有 3 个 class ,分别是 Man,Woman,Person。 其中 Man 和 Woman 都继承自 Person 。app
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
#import "Person.h"
@implementation Person
+(void)initialize{
NSLog(@"call person initialize");
}
@end
复制代码
#import "Person.h"
@interface Man : Person
@end
#import "Man.h"
@implementation Man
@end
复制代码
#import "Person.h"
@interface Woman : Person
@end
#import "Woman.h"
@implementation Woman
@end
复制代码
在 main.m 方法代码以下:ui
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
}
return 0;
}
复制代码
咱们运行程序获得以下输出this
call person initialize
复制代码
在 Person 的 initialize 方法设置断点,查看堆栈调用,Person 调用的第一个方法确实是 initialize ,该方法在 Person 收到第一个消息以前初始化 Person。spa
接下来修改 main.m 的代码,同时生成 Person ,Man,Woman 的对象实例。线程
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
Man *m = [[Man alloc] init];
Woman *w = [[Woman alloc] init];
}
return 0;
}
复制代码
运行程序,查看控制台输出code
call person initialize
call person initialize
call person initialize
复制代码
咱们能够看出若是子类没有实现 initialize 方法,runtime 会调用父类的 initialize 实现,那么咱们就不用在子类中调用 [super initialize] ,同时也意味着父类的 initialize 会被屡次调用,那么咱们能够采用以下的方式来避免这个问题。orm
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
复制代码
那若是 Person子类 Man 和 Woman 都实现 initialize 方法呢?cdn
@implementation Man
+(void)initialize{
NSLog(@"call man initialize");
}
+(void)initialize{
NSLog(@"call woman initialize");
}
@end
复制代码
运行程序,查看控制台输出,能够看到 class 都是调用各自的 initialize 方法实现。
call person initialize
call man initialize
call woman initialize
复制代码
每一个 class 有且仅有一次 initialize 方法调用,若是想要实现 class 和 category 的分别独立初始化,咱们应该使用 load 方法。
看文档能够得知 class 或者 category 被添加到 runtime 的时候,load 方法就会被调用。
Invoked whenever a class or category is added to the Objective-C runtime;
implement this method to perform class-specific behavior upon loading.
+ (void)load;
复制代码
接下来咱们用代码来探究 load 这个方法,仍是用以前的例子,咱们有 3 个 class ,分别是 Man,Woman,Person。 其中 Man 和 Woman 都继承自 Person 。
Person 类实现了 load 方法
//Person.m
#import "Person.h"
@implementation Person
+(void)initialize{
NSLog(@"call person initialize");
}
+(void)load{
NSLog(@"call person load");
}
// main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
}
return 0;
}
@end
复制代码
运行程序,查看控制台输出,能够看出 load 方法调用在 initialize 方法以前。
call person load
call person initialize
复制代码
接下来修改 main.m 实现
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
#import "Woman.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
Man *m = [[Man alloc] init];
Woman *w = [[Woman alloc] init];
}
return 0;
}
复制代码
运行程序,查看控制台输出,能够看出子类没有实现 load 方法的时候,runtime 不会自动调用父类的 load 方法实现
call person load
call person initialize
call man initialize
call woman initialize
复制代码
接下来修改 Man.m 和 Woman.m 实现
// Man.m
#import "Man.h"
@implementation Man
+(void)initialize{
NSLog(@"call man initialize");
}
+(void)load{
NSLog(@"call man load");
}
@end
// Woman.m
#import "Woman.h"
@implementation Woman
+(void)initialize{
NSLog(@"call woman initialize");
}
+(void)load{
NSLog(@"call woman load");
}
@end
复制代码
运行程序,查看控制台输出,能够看出,咱们没有在 Woman 和 Man 中显式调用父类的 load 方法,可是父类的 load 方法调用都在子类以前,这个和 initialize 方法是同样的,毕竟是要先有父类初始化,才会有子类初始化。
call person load
call woman load
call man load
call person initialize
call man initialize
call woman initialize
复制代码
接下来新建一个 Man 的 category 叫作 Man(Work),
// Mam + Work.m
#import "Man+Work.h"
@implementation Man (Work)
+(void)load{
NSLog(@"call Man (Work) load");
}
@end
复制代码
运行程序,查看控制台输出,能够看出 category 的 load 方法调用老是在 class 的 load 方法调用以后。
call man load
call Man (Work) load
call man initialize
复制代码
经过一些代码例子和官方文档,咱们能够知道 initialize 方法的做用是在 class 收到第一个消息以前初始化 class。load 方法的调用时机是在 class 或者 category 被添加到 runtime 的时候。load 方法调用在 initialize 方法以前。