iOS開發(fā)面試時經(jīng)常被問到,+load方法和+initialize方法糠赦。今天主要用源碼分析下各自的調(diào)用機制。
+load方法
當(dāng)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ā)送消息流程的流程。
圖八
當(dāng)這個已經(jīng)初始化且沒有發(fā)送過initialize方法時,就會執(zhí)行
_class_initialize
函數(shù)识藤。這個函數(shù)有三個主要邏輯:如下四張圖.圖九
圖十
圖十一
圖十二
- 遞歸的查找父類砚著,直到NSObject類。
- +initialize方法只能被調(diào)用一次痴昧。
- 調(diào)用順序:
- 父類有子類都有分類:先是父類的分類,再是子類的分類
- 父類沒有分類子類有分類:先是父類,再是子類的分類
- 父類有分類子類沒有:先是父類的分類,再是子類
- 父類子類都沒有:先是父類,再是子類稽穆。