在 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方法的調用順序是先父類再子類;是以懶加載的方式被調用的;