1. 調(diào)用順序
以main為分界,load方法在main函數(shù)之前執(zhí)行,initialize在main函數(shù)之后執(zhí)行
2.相同點和不同點
2.1 相同點
- load和initialize會被自動調(diào)用,不能手動調(diào)用它們。
- 子類實現(xiàn)了load和initialize的話,會隱式調(diào)用父類的load和initialize方法
- load和initialize方法內(nèi)部使用了鎖,因此它們是線程安全的。
2.2 不同點
- 子類中沒有實現(xiàn)load方法的話,不會調(diào)用父類的load方法;而子類如果沒有實現(xiàn)initialize方法的話,也會自動調(diào)用父類的initialize方法。
- load方法是在類被裝在進來的時候就會調(diào)用,initialize在第一次給某個類發(fā)送消息時調(diào)用(比如實例化一個對象),并且只會調(diào)用一次,是懶加載模式,如果這個類一直沒有使用,就不回調(diào)用到initialize方法。
3. load
在執(zhí)行l(wèi)oad方法之前,會調(diào)用load_images方法,用來掃描鏡像中的+ load符號,將需要調(diào)用 load 方法的類添加到一個列表中loadable_classes,在這個列表中,會先把父類加入到待加載列表,這樣保證父類在父類在子類錢調(diào)用load方法,而分類中的load方法會在類的load的方法后面加入另外一個待加載列表loadable_categories,這樣保證了兩個規(guī)則:
- 父類先于子類調(diào)用
- 類先于分類調(diào)用
在掃描完load方法加入到待加載方法后,會調(diào)用call_load_methods,先從loadable_classes調(diào)用類的load方法,call_class_loads;調(diào)用完loadable_classes后會調(diào)用loadable_categories中分類的load方法,call_category_loads。
調(diào)用順序如下:
- 父類load先于類添加到loadable_classes列表,通過call_class_loads,調(diào)用列表中的load方法,這樣父類的load先于類的load執(zhí)行
- 當loadable_classes為空的時候,查看loadable_classes是否為空,如果不為空則調(diào)用call_category_loads加載分類中的load方法,這樣分類的load在類之后執(zhí)行
4. initialize
initialize 只會在對應類的方法第一次被調(diào)用時,才會調(diào)用,initialize 方法是在 alloc 方法之前調(diào)用的,alloc 的調(diào)用導致了前者的執(zhí)行。
initialize的調(diào)用棧中,直接調(diào)用其方法的其實是_class_initialize 這個C語言函數(shù),在這個方法中,主要是向為初始化的類發(fā)送+initialize消息,不過會強制父類先發(fā)送。
與 load 不同,initialize 方法調(diào)用時,所有的類都已經(jīng)加載到了內(nèi)存中。
5. 使用場景
5.1 load
load一般是用來交換方法Method Swizzle,由于它是線程安全的,而且一定會調(diào)用且只會調(diào)用一次,通常在使用UrlRouter的時候注冊類的時候也在load方法中注冊
5.2 initialize
initialize方法主要用來對一些不方便在編譯期初始化的對象進行賦值,或者說對一些靜態(tài)常量進行初始化操作