+load和+initialize方法調用時機
一、+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方法)