記錄一下initialize和load方法的調(diào)用時機
問題一 load和initialize哪個更早執(zhí)行?
1. main函數(shù)
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
NSLog(@"%s",__FUNCTION__);
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
2. 繼承自NSObject的Person類
#import "Person.h"
@implementation Person
+ (void)load {
NSLog(@"%s",__FUNCTION__);
}
+ (void)initialize {
[super initialize];
NSLog(@"%s %@",__FUNCTION__, [self class]);
}
- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"%s",__FUNCTION__);
}
return self;
}
@end
運行--結(jié)果

只執(zhí)行了load, 未調(diào)用initialize, 猜測是因為未實例化Person對象
3. 實例化Person對象
在ViewController中為Person創(chuàng)建一個實例對象
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person *p1 = [Person new];
}
運行--結(jié)果

可以看到, 先調(diào)用load, 然后調(diào)用main, 由于實例化了一個Person對象, 所以調(diào)用了initialize方法, 最后是init方法
結(jié)論2:
load早于main早于initialize早于init
還有一些大神總結(jié)的區(qū)別
load
對于加入運行期系統(tǒng)的類及分類,必定會調(diào)用此方法,且僅調(diào)用一次。
iOS會在應(yīng)用程序啟動的時候調(diào)用load方法,在main函數(shù)之前調(diào)用
執(zhí)行子類的load方法前,會先執(zhí)行所有超類的load方法,順序為父類->子類->分類
在load方法中使用其他類是不安全的,因為會調(diào)用其他類的load方法,而如果關(guān)系復(fù)雜的話,就無法判斷出各個類的載入順序,類只有初始化完成后,類實例才能進行正常使用
load 方法不遵從繼承規(guī)則,如果類本身沒有實現(xiàn)load方法,那么系統(tǒng)就不會調(diào)用,不管父類有沒有實現(xiàn)(跟下文的initialize有明顯區(qū)別)
盡可能的精簡load方法,因為整個應(yīng)用程序在執(zhí)行l(wèi)oad方法時會阻塞,即,程序會阻塞直到所有類的load方法執(zhí)行完畢,才會繼續(xù)
load 方法中最常用的就是方法交換method swizzling
initialize
在首次使用該類之前由運行期系統(tǒng)(非人為)調(diào)用,且僅調(diào)用一次
惰性調(diào)用,只有當(dāng)程序使用相關(guān)類時,才會調(diào)用
運行期系統(tǒng)會確保initialize方法是在線程安全的環(huán)境中執(zhí)行,即,只有執(zhí)行initialize的那個線程可以操作類或類實例。其他線程都要先阻塞,等待initialize執(zhí)行完
-
如果類未實現(xiàn)initialize方法,而其超類實現(xiàn)了,那么會運行超類的實現(xiàn)代碼,而且會運行兩次(load 第5點)
(1) initialize 遵循繼承規(guī)則
(2) 初始化子類的的時候會先初始化父類,然后會調(diào)用父類的initialize方法,而子類沒有覆寫initialize方法,因此會再次調(diào)用父類的實現(xiàn)方法
(3) 鑒于此,initialize方法實現(xiàn)如下:
+ (void)initialize {
if (self == [People class]) {
NSLog(@"%@ initialize", self);
}
}
- initialize方法也需要盡量精簡,一般只應(yīng)該用來設(shè)置內(nèi)部數(shù)據(jù),比如,某個全局狀態(tài)無法在編譯期初始化,可以放在initialize里面。
static NSMutableArray *kSomeObjects;
@implementation People
+ (void)initialize {
if (self == [People class]) {
kSomeObjects = [NSMutableArray new];
}
}