一、+load方法什麼時候呼叫
+load方法會在runtime載入類、分類時呼叫(程式執行起來會先去載入呼叫+load 跟你引用沒有引用其標頭檔案沒有關係)。
每個類、分類的+load,在程式執行過程中只呼叫一次。
呼叫順序:
-
先呼叫類的+load
- 按照編譯先後順序呼叫(先編譯,先呼叫)
- 呼叫子類的+load之前會先呼叫父類的+load
-
再呼叫分類的+load
- 按照編譯先後順序呼叫(先編譯,先呼叫)
二、為什麼原本類的+load方法不會被分類的+load方法覆蓋呢?
這是由於+load方法是根據方法地址直接呼叫,並不是經過objc_msgSend函式呼叫。
+load方法相關原始碼閱讀順序:
- _objc_init
- load_images
- prepare_load_methods
- schedule_class_load
- add_class_to_loadable_list
- add_category_to_loadable_list
- calls
- call_class_loads
- call_category_loads
- (*load_method)(cls, SEL_load)
三、+initialize方法呼叫的時機
+initialize方法會在類第一次接收到訊息時呼叫。
呼叫順序:先呼叫父類的+initialize,再呼叫子類的+initialize,每個類只會初始化1次
+initialize方法相關原始碼閱讀順序:
-
objc-msg-arm64.s
- objc_msgSend
-
objc-runtime-new.mm
- class_getInstanceMethod
- lookUpImpOrNil
- lookUpImpOrForward
- _class_initialize
- callInitialize
- objc_msgSend(cls, SEL_initialize)
+initialize和+load的最大區別是,+initialize是通過objc_msgSend進行呼叫的,所以有以下特點:
- 如果子類沒有實現+initialize,會呼叫父類的+initialize(所以父類的+initialize可能會被呼叫多次)
- 如果分類實現了+initialize,就覆蓋類本身的+initialize呼叫
四、總結
load、initialize方法的區別什麼?
1.呼叫方式
1> load是根據函式地址直接呼叫
2> initialize是通過objc_msgSend呼叫
2.呼叫時刻
1> load是runtime載入類、分類的時候呼叫(只會呼叫1次)
2> initialize是類第一次接收到訊息的時候呼叫,每一個類只會initialize一次(父類的initialize方法可能會被呼叫多次)
load、initialize的呼叫順序?
1.load
1> 先呼叫類的load
a) 先編譯的類,優先呼叫load
b) 呼叫子類的load之前,會先呼叫父類的load
2> 再呼叫分類的load
a) 先編譯的分類,優先呼叫load
2.initialize
1> 先初始化父類
2> 再初始化子類(可能最終呼叫的是父類的initialize方法)