iOS開發(fā)面試時經(jīng)常被問到,+load方法和+initialize方法。今天主要用源碼分析下各自的調(diào)用機制。
+load方法
當APP啟動的時候,dyld便會開始加載庫和鏈接庫。load_images這個函數(shù)便會執(zhí)行,這個函數(shù)就會執(zhí)行+load方法。

圖一
這里邊有兩個重要的函數(shù):
prepare_load_methods和call_load_methods,一個是準備load方法,一個是調(diào)用load方法。
1.prepare_load_methods方法

圖二
在準備load方法里邊又分為獲取類的load表和獲取分類的load表。
1.獲取類的load表

圖三

圖四
- 進入
schedule_class_load函數(shù),將會遞歸的找到父類一直到NSObject。 - 將重載load方法的類添加到
loadable_classes這個表里,按從父類到子類的順序。沒有重載load方法的類忽略。
2.獲取分類的load表

圖五
將所有重載load方法的分類加入到
loadable_categories表里邊,沒有重載load方法的分類忽略。
2.call_load_methods方法

圖六
由
call_load_methods函數(shù)可以看到,先執(zhí)行了類的load方法調(diào)用,然后才執(zhí)行了分類的load方法調(diào)用。
3.+load方法總結(jié)
- +load方法在mian函數(shù)之前調(diào)用,因為dyld完成之后才會到main函數(shù)。
- 自動調(diào)用且由系統(tǒng)統(tǒng)一調(diào)用。
- 執(zhí)行順序:先是父類,然后是子類,最后才是分類。
+initialize方法

圖七
給+initialize方法加入斷點,可以很清楚的看到initialize方法是在main函數(shù)之后執(zhí)行的,且是被動調(diào)用的,因為它走的是發(fā)送消息流程的流程。

圖八
當這個已經(jīng)初始化且沒有發(fā)送過initialize方法時,就會執(zhí)行
_class_initialize函數(shù)。這個函數(shù)有三個主要邏輯:如下四張圖.
圖九

圖十

圖十一

圖十二
- 遞歸的查找父類,直到NSObject類。
- +initialize方法只能被調(diào)用一次。
- 調(diào)用順序:
- 父類有子類都有分類:先是父類的分類,再是子類的分類
- 父類沒有分類子類有分類:先是父類,再是子類的分類
- 父類有分類子類沒有:先是父類的分類,再是子類
- 父類子類都沒有:先是父類,再是子類。