+load和+initialize
+load 與 +initialize 的異同
-
+load方法會在 main() 函數(shù)之前調(diào)用,而+initialize是在類第一次使用時才會調(diào)用 -
+load方法調(diào)用優(yōu)先級:父類>子類>分類,并且不會被覆蓋,均會調(diào)用 -
+initialize調(diào)用優(yōu)先級:分類>父類,父類>子類,父類的分類重寫了+initialize方法會覆蓋父類的+initialize方法。即:- 如果分類和父類均實現(xiàn)了
+initialize,則只有分類的+initialize會被調(diào)用; - 如果父類和子類均實現(xiàn)了
+initialize,第一次引用 子類時,先調(diào)用父類的+initialize,再調(diào)用子類的+initialize; - 如果父類實現(xiàn)了
+initialize,則第一次引用子類時,會調(diào)用兩次父類的+initialize
- 如果分類和父類均實現(xiàn)了
-
+load方法在 main() 函數(shù)之前調(diào)用,所有的類文件都會加載,分類也會加載 - 均無須顯式調(diào)用 super 方法
load
由于 +load 方法在 App 啟動加載的時候調(diào)用,此時不能保證所有的類被加載完成。
+load 方法是線程安全的,因為內(nèi)部有鎖,但是也帶了一定的性能開銷。所以一般會在 +load 方法中實現(xiàn) Method Swizzle
調(diào)用順序是父類->子類->分類。
多個分類中實現(xiàn)了+load方法,根據(jù)Compile Source中的順序決定。但要遵循調(diào)用[ChildClass load]之前,必須先調(diào)用其[SuperClass load]方法。
load 方法是直接使用函數(shù)指針調(diào)用,即走 C 語言函數(shù)調(diào)用的流程,不是發(fā)送消息,并不會走消息轉(zhuǎn)發(fā)流程,也就是說如果一個類實現(xiàn)了 load 函數(shù)就會調(diào)用,如果沒有實現(xiàn)也不會調(diào)用該類的父類 load 函數(shù)。
+initialize 方法
父類->子類,分類會覆蓋類,如果子類沒有實現(xiàn) initialize 方法,父類會調(diào)用兩次
子類實現(xiàn)了 initialize,會先調(diào)用父類 initialize,再調(diào)用子類 initialize
子類沒有實現(xiàn) initialize,父類 initialize 方法會調(diào)用兩次
如果先引用父類的實例對象,再引用子類實例對象,則會在引用父類實例對象時調(diào)用父類 initialize 方法;當(dāng)引用子類實例對象時,由于父類的 initialize 方法已經(jīng)執(zhí)行,所以此時只調(diào)用子類 initialize 方法
如果先引用子類的實例對象,再引用父類的實例對象,則會在引用子類的實例對象時,在調(diào)用 initialize 方法前,先調(diào)用父類 initialize 方法,再調(diào)用子類的 initialize 方法;當(dāng)引用父類實例對象時,由于在引用子類實例對象時已經(jīng)調(diào)用了 initialzie 方法了,此時不再調(diào)用 initialize 方法
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
或者使用 dispatch_once
load 函數(shù)的調(diào)用直接是函數(shù)指針的調(diào)用,而 initialize 函數(shù)是消息轉(zhuǎn)發(fā)。所以 class 的子類就算沒有實現(xiàn) initialize 函數(shù),也會調(diào)用父類的 initialize 函數(shù)