在 iOS 开发中,我们经常会使用 +load 方法来做一些在 main
函数之前的操作,比如方法交换(Method Swizzle)等。现在分析一下load方法跟initialize方法的调用顺序以及区别。
1.先看下load方法
尝试定义一个继承自 NSObject
的 Person
类,并对其添加两个分类 Life
和 Work
;再定义一个 Student
类继承自 Person
,并对其添加 School
分类。在以上所有类和分类中,均实现 +load:
#import "Person.h"
@implementation Person
+ (void)load {
NSLog(@"Person %s", __func__);
}
@end
#import "Person+Life.h"
@implementation Person (Life)
+ (void)load {
NSLog(@"Person+Life %s", __func__);
}
@end
#import "Person+Work.h"
@implementation Person (Work)
+ (void)load {
NSLog(@"Person+Work %s", __func__);
}
@end
#import "Student.h"
@implementation Student
+ (void)load {
// [super load];
NSLog(@"Student %s", __func__);
}
@end
#import "Student+School.h"
@implementation Student (School)
+ (void)load {
NSLog(@"Student+School %s", __func__);
}
@end
启动项目,打印结果如下,说明 +load 方法会在 main
函数之前被调用;且调用顺序总是先父类再子类再分类。
当我们在一个类的子类的 +load 中 [super load]
又会调用到到底哪个类中呢(当然,在实际开发中这种情几乎不可能存在)?答案就是 [super load]
将调用到 Person
最后一个被编译的分类(Person+Work
)中的 +load
方法,因为这里是消息发送,而不是通过方法指针。
应用:因为类或者分类一旦被加载到运行时,就会调用这个方法;因为加载时间特别早:所以可以利用这个特性进行一些处理
2.之后分析 initialize方法
在person与student类中添加init方法跟initialize方法,然后在 ViewController 中创建 Person 和 student 对象,如下:
#import "Person.h"
@implementation Person
-(instancetype)init{
if (self = [super init]) {
NSLog(@"%s",__func__);
}
return self;
}
+ (void)load {
NSLog(@"Person %s", __func__);
}
+ (void)initialize{
NSLog(@"Person %s",__func__);
}
@end
#import "Student.h"
@implementation Student
-(instancetype)init{
if (self = [super init]) {
NSLog(@"%s",__func__);
}
return self;
}
+ (void)load {
NSLog(@"Student %s", __func__);
}
+ (void)initialize{
NSLog(@"Student %s",__func__);
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%s",__func__);
Person * per = [[Person alloc]init];
Student * stu = [[Student alloc]init];
// Do any additional setup after loading the view, typically from a nib.
}
启动项目,运行结果如下:
由此得出结论
load
和initialize
方法都会在实例化对象之前调用,以main函数为分水岭,前者在main函数之前调用,后者在之后调用。- initialize方法的调用顺序是先父类再子类;是以懒加载的方式被调用的;