真的了解 + load 方法么?
+load 作為 Objective-C 中的一個方法,與其它方法有很大的不同。它只是一個在整個文件被加載到運行時,在 main 函數(shù)調用之前被 ObjC 運行時調用的鉤子方法。其中關鍵字有這么幾個:
- 文件剛加載
- main函數(shù)之前
- 鉤子方法
準備 + load 方法
在load_images 方法,如果在掃描鏡像的過程中發(fā)現(xiàn)了 + load 符號
就會進入 load_images_nolock 來查找 load 方法
調用 prepare_load_methods 對 load 方法的調用進行準備(將需要調用 load 方法的類添加到一個列表中,后面的小節(jié)中會介紹)
通過 _getObjc2NonlazyClassList 獲取所有的類的列表之后,會通過 remapClass 獲取類對應的指針,然后調用 schedule_class_load 遞歸地安排當前類和沒有調用 + load 父類進入列表。
在執(zhí)行 add_class_to_loadable_list(cls) 將當前類加入加載列表之前,會先把父類加入待加載的列表,保證父類在子類前調用 load 方法。
調用 + load 方法
在將鏡像加載到運行時、對 load 方法的準備就緒之后,執(zhí)行 call_load_methods,開始調用 load 方法
其中 call_class_loads 會從一個待加載的類列表 loadable_classes 中尋找對應的類,然后找到 @selector(load) 的實現(xiàn)并執(zhí)行。
調用順序如下:
1.不停調用類的 + load 方法,直到 loadable_classes 為空
2.調用一次 call_category_loads 加載分類
3.如果有 loadable_classes 或者更多的分類,繼續(xù)調用 load 方法
相比于類 load 方法的調用,分類中 load 方法的調用就有些復雜了:
1.獲取當前可以加載的分類列表
2.如果當前類是可加載的 cls && cls->isLoadable() 就會調用分類的 load 方法
3.將所有加載過的分類移除 loadable_categories 列表
4.為 loadable_categories 重新分配內存,并重新設置它的值
調用的順序
對于 load 方法的調用順序有兩條規(guī)則:
父類先于子類調用
類先于分類調用
load 的應用
load 可以說我們在日常開發(fā)中可以接觸到的調用時間最靠前的方法,在主函數(shù)運行之前,load 方法就會調用。
由于它的調用不是惰性的,且其只會在程序調用期間調用一次,最最重要的是,如果在類與分類中都實現(xiàn)了 load 方法,它們都會被調用,不像其它的在分類中實現(xiàn)的方法會被覆蓋,這就使 load 方法成為了方法調劑的絕佳時機。
但是由于 load 方法的運行時間過早,所以這里可能不是一個理想的環(huán)境,因為某些類可能需要在在其它類之前加載,但是這是我們無法保證的。不過在這個時間點,所有的 framework 都已經(jīng)加載到了運行時中,所以調用 framework 中的方法都是安全的。