?pre-main
?靜態(tài)庫
?匯編生成的目標(biāo)與引用的庫一起打包到可執(zhí)行文件生成最終的mach-o二進(jìn)制可執(zhí)行文件
?動態(tài)庫
?程序編譯的時候不會鏈接到動態(tài)庫,程序運(yùn)行才會鏈接, 動態(tài)庫包括uikit, foundation,corefoundation, libdispatch,dyld等
?dyld會首先讀取mach-o的header和loadcommonds,獲取路徑,加載相關(guān)依賴庫,例如加載動態(tài)庫A到內(nèi)存,然后檢查A所依賴的動態(tài)庫
?(通常一個APP要加載的動態(tài)庫100-400個),
?load_images方法主要做兩件事, prepare_load_methods? call_load_methods, 在call_load_methods里先調(diào)用 class_loads,再調(diào)用 category_loads
?即先去除類,父類和分類的load方法, 第二步加載這些load方法, load方法在這里進(jìn)行初始化
?+load方法應(yīng)用場景 (hook方法 / 組件化開發(fā), 不同組件之間的通信,在load方法中注冊協(xié)議)
?1. +load是在類和分類在加載時調(diào)用的, 2. 只調(diào)用一次
?順序是
?1. 類優(yōu)先與分類調(diào)用
?2. 子類調(diào)用+load時,先調(diào)用父類的+load, ( 父類優(yōu)先于子類, 與繼承不同)
?3. 不同類按照編譯順序調(diào)用+load方法(先編譯先調(diào)用)
?4, 分類也是按照編譯順序調(diào)用+load方法(先編譯先調(diào)用)
其中:
schedule_class_load(cls->superclass); //在調(diào)度類的load方法前草戈,要先跳用父類的load方法(遞歸)诡壁,決定了父類優(yōu)先于子類調(diào)用
add_class_to_loadable_list(cls);? //添加到能夠加載的類的列表中
當(dāng)prepare_load_methods函數(shù)執(zhí)行完之后凄贩,所有滿足+load方法調(diào)用條件的類和分類就被分別保持在全局變量中断国; 等待執(zhí)行
當(dāng)prepare_load_methods執(zhí)行完爪瓜,準(zhǔn)備好類和分類后甘苍,就該調(diào)用他們的+load方法啦伴榔,在call_load_methods中進(jìn)行調(diào)用礁击;注意圖中紅色圈內(nèi)部分,兩個關(guān)鍵函數(shù):call_class_loads()妖泄,call_category_loads() 驹沿;看到這兩個函數(shù)想到了什么呢?
對蹈胡,就是這兩個函數(shù)決定了類優(yōu)先與分類調(diào)用+load方法渊季;
說明:+load方法是系統(tǒng)根據(jù)方法地址直接調(diào)用,并不是objc_msgSend函數(shù)調(diào)用(isa罚渐,superClass)却汉;這就決定了如果子類沒有實現(xiàn)+load方法,那么當(dāng)它被加載時runtime是不會調(diào)用父類的+load方法的荷并,除非父類也實現(xiàn)了+load方法合砂;