+load 與 +initialize的區別
阿新 • • 發佈:2019-01-04
先附上程式碼,load 方法的程式碼 我就不附上,大家可以自己動手測試一下。
@interface XZPerson : NSObject @end #import "XZPerson.h" @implementation XZPerson + (void)initialize{ NSLog(@"XZPerson-initialize"); } @end ////////////////////////////////////////////////////////////////////////////// #import "XZPerson.h" @interface XZPerson (Eat) @end #import "XZPerson+Eat.h" @implementation XZPerson (Eat) + (void)initialize{ NSLog(@"XZPerson(Eat)-initialize"); } @end ////////////////////////////////////////////////////////////////////////////// #import "XZPerson.h" @interface XZPerson (Drink) @end @implementation XZPerson (Drink) + (void)initialize{ NSLog(@"XZPerson(Eat)-initialize"); } @end ////////////////////////////////////////////////////////////////////////////// #import "XZPerson.h" @interface XZStudent : XZPerson @end #import "XZStudent.h" @implementation XZStudent + (void)initialize{ NSLog(@"XZStudent-initialize"); } @end ////////////////////////////////////////////////////////////////////////////// #import "XZStudent.h" @interface XZStudent (Test1) @end #import "XZStudent+Test1.h" @implementation XZStudent (Test1) + (void)initialize{ NSLog(@"XZStudent(Test1)-initialize"); } @end ////////////////////////////////////////////////////////////////////////////// #import "XZStudent.h" @interface XZStudent (Test2) @end #import "XZStudent+Test2.h" @implementation XZStudent (Test1) + (void)initialize{ NSLog(@"XZStudent(Test2)-initialize"); } @end
結論如下:
一,+load 方法 會在runtime 載入類/分類時呼叫 在程式執行過程中只會呼叫一次。
- 先呼叫類的+ load ,按照編譯順序來,先編譯先呼叫
- 在呼叫子類的+load 方法之前,會先呼叫父類的。
- 假如類有分類,會優先呼叫分類的+load
- + load的方法是根據方法地址直接呼叫,並不是經過objc_msgSend 函式呼叫的。
- 可以參考runtime的原始碼,objc-os.mm 中的_objc_init 方法中檢視load_images等等
二,+initialize方法會在類第一次接收訊息食呼叫
- 先呼叫父類的+initialize方法,在呼叫子類的,只會初始化一次
- 如果子類沒有實現+initialize方法會優先呼叫父類的initialize方法,所以父類的initialize方法會被呼叫多次
- 如果分類呼叫了+initialize方法,那麼它會覆蓋本身的initialize方法
- 按照編譯順序,後編譯的分類有先呼叫。
- +initialize是通過objc_msgSend呼叫的。