可能有些還不清楚load和initialize的區別,下面簡單說一下:
首先說一下 + initialize 方法:蘋果官方對這個方法有這樣的一段描述:這個方法會在 第一次初始化這個類之前 被調用,我們用它來初始化靜態變量.
initialize方法的調用時機,當向該類發送第一個消息(一般是類消息首先調用,常見的是alloc)的時候,先調用類中的,再調用類別中的(類別中如果有重寫);如果該類只是引用,沒有調用,則不會執行initialize方法。
兩者方法的共同點:自動調用父類的,不需要super操作;自動調用僅僅會調用一次(不包括外部顯示調用).
load 方法會在加載類的時候就被調用,也就是 ios 應用啟動的時候,就會加載所有的類,就會調用每個類的 + load 方法.
load方法的調用時機,main函數之前,先調用類中的,再調用類別中的(類別中如果有重寫).
代碼演示:
#pragram ---main函數中的代碼--- #import <UIKit/UIKit.h> #import "AppDelegate.h" int main(int argc, char * argv[]) { NSLog(@"%s",__func__); @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } #pragram ---基於NSObject的Person類--- #import "Person.h" @implementation Person + (void)load{ NSLog(@"%s",__func__); } + (void)initialize{ [super initialize]; NSLog(@"%s %@",__func__,[self class]); } - (instancetype)init{ if (self = [super init]) { NSLog(@"%s",__func__); } return self; } @end #pragram ---基於Person的Son類--- #import "Girl.h" @implementation Girl + (void)load{ NSLog(@"%s ",__func__); } + (void)initialize{ [super initialize]; NSLog(@"%s ",__func__); } - (instancetype)init{ if (self = [super init]) { NSLog(@"%s",__func__); } return self; } @end
輸出日志:
2017-07-07 09:28:36.535 initialize[1572:27457]] +[Person load] 2017-07-07 09:28:36.535 initialize[1572:27457]] +[Girl load] 2017-07-07 09:28:36.535 initialize[1572:27457]] main
這說明在我並沒有對類做任何操作的情況下,+load 方法會被默認執行,並且是在 main 函數之前執行的。
#接下來我們來查看一下 + initialize 方法,先在 ViewController 中創建 Person 和 Girl 對象:
#import "ViewController.h" #import "Person.h" #import "Son.h" #import "Girl.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Person * p1 = [Person new]; Person * p2 = [Person new]; Girl *c1 = [Girl new]; Girl *c2 = [Girl new]; } @end
輸出日志:
2017-07-07 09:34:57.134 initialize[1840:100060] +[Person load] 2017-07-07 09:34:57.135 initialize[1840:100060] +[Girl load] 2017-07-07 09:34:57.136 initialize[1840:100060] main 2017-07-07 09:34:57.198 initialize[1840:100060] +[Person initialize] Person 2017-07-07 09:34:57.198 initialize[1840:100060] -[Person init] 2017-07-07 09:34:57.198 initialize[1840:100060] -[Person init] 2017-07-07 09:34:57.198 initialize[1840:100060] +[Girl initialize] 2017-07-07 09:34:57.199 initialize[1840:100060] -[Girl init] 2017-07-07 09:34:57.199 initialize[1840:100060] -[Girl init]
+ initialize 方法類似一個懶加載,如果沒有使用這個類,那么系統默認不會去調用這個方法,且默認只加載一次;
+ initialize 的調用發生在 +init 方法之前.
那么+ initialize 在父類與子類之間的關系是什么楊,我們創建一個繼承自 Person 類的 Son類:
#pragram ---ViewController 中的代碼--- #import "ViewController.h" #import "Person.h" #import "Son.h" #import "Girl.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Person * p1 = [Person new]; Person * p2 = [Person new]; Son*s = [Son new]; } @end
輸出日志:
2017-07-07 09:50:14.140 initialize[1893:109979] +[Person load] 2017-07-07 09:50:14.142 initialize[1893:109979] +[Son load] 2017-07-07 09:50:14.142 initialize[1893:109979] +[Girl load] 2017-07-07 09:50:14.142 initialize[1893:109979] main 2017-07-07 09:50:14.203 initialize[1893:109979] +[Person initialize] Person 2017-07-07 09:50:14.203 initialize[1893:109979] -[Person init] 2017-07-07 09:50:14.203 initialize[1893:109979]] -[Person init] 2017-07-07 09:50:14.204 initialize[1893:109979] +[Person initialize] Son 2017-07-07 09:50:14.204 initialize[1893:109979] -[Person init]
我們會發現 Person 類的 + initialize 方法又被調用了,但是查看一下是子類 Son 調用的,也就是創建子類的時候,子類會去調用父類的 + initialize 方法。
這是因為在創建子類對象時,首先要創建父類對象,所以會調用一次父類的initialize
方法,然后創建子類時,盡管自己沒有實現initialize
方法,但還是會調用到父類的方法。
雖然initialize
方法對一個類而言只會調用一次,但這里由於出現了兩個類,所以調用兩次符合規則,但不符合我們的需求。正確使用initialize
方法的姿勢如下
// In Person.m + (void)initialize { if (self == [Person class]) { NSLog(@"Initialize Person, caller Class %@", [self class]); } }
加上判斷后,就不會因為子類而調用到自己的initialize
方法了.
總結:
load
和initialize
方法都會在實例化對象之前調用,以main函數為分水嶺,前者在main函數之前調用,后者在之后調用。這兩個方法會被自動調用,不能手動調用它們。load
和initialize
方法都不用顯示的調用父類的方法而是自動調用,即使子類沒有initialize
方法也會調用父類的方法,而load
方法則不會調用父類。load
方法通常用來進行Method Swizzle,initialize
方法一般用於初始化全局變量或靜態變量。load
和initialize
方法內部使用了鎖,因此它們是線程安全的。實現時要盡可能保持簡單,避免阻塞線程,不要再使用鎖。