load方法和initialize方法

load

在聯(lián)想到viewDidLoad等方法時(shí)很容易在內(nèi)心中萌生一種錯(cuò)誤的想法,在參考了1個(gè)帖子后終于對(duì)load方法有了一個(gè)大概的理解

1.load函數(shù)的加載時(shí)機(jī)

簡(jiǎn)單來(lái)說(shuō)load方法是在這個(gè)文件被程序裝載時(shí)調(diào)用,因此load方法是在main方法調(diào)用前調(diào)用

2.load方法調(diào)用的順序

superClass -> class -> category

3.load方法的作用和使用場(chǎng)景

由于load的調(diào)用時(shí)機(jī)比較早,通常是在A(yíng)pp啟動(dòng)加載的時(shí)候開(kāi)始,這時(shí)候并不能保證所有的類(lèi)都被加載完成并且可以使用。并且load加載自身也存在不確定性,因?yàn)樵谟幸蕾?lài)關(guān)系的兩個(gè)庫(kù)中,被依賴(lài)的類(lèi)的load方法會(huì)先調(diào)用,但是在一個(gè)庫(kù)之內(nèi)調(diào)用的順序是不確定的。除此之外,load方法是線(xiàn)程安全的,因?yàn)閮?nèi)部實(shí)現(xiàn)加上了鎖,但是也帶來(lái)了一定的性能開(kāi)銷(xiāo),所以不適合處理很復(fù)雜的事情。一般,會(huì)在load方法實(shí)現(xiàn)Method Swizzle(方法交換實(shí)現(xiàn))。


load方法是直接使用函數(shù)指針調(diào)用,也就是走C語(yǔ)言函數(shù)調(diào)用的流程,不是發(fā)送消息,并不會(huì)走消息轉(zhuǎn)發(fā)的流程,也就是說(shuō),如果一個(gè)類(lèi)實(shí)現(xiàn)了load函數(shù)就會(huì)調(diào)用,如果沒(méi)有實(shí)現(xiàn)也不會(huì)調(diào)用該類(lèi)的父類(lèi)load函數(shù)實(shí)現(xiàn),如果父類(lèi)實(shí)現(xiàn)了load函數(shù)的話(huà)。category調(diào)用load方法也是一樣的道理。

initialize

1.initialize函數(shù)的加載時(shí)機(jī)

這個(gè)函數(shù)是懶加載,只有當(dāng)類(lèi)接收了第一個(gè)消息的時(shí)候才會(huì)調(diào)用initialize函數(shù),否則一直不會(huì)調(diào)用。

2.initialize函數(shù)的調(diào)用順序

initialize函數(shù)的調(diào)用順序?yàn)椋簊uperClass -> class。這里沒(méi)有分類(lèi),因?yàn)橐粋€(gè)類(lèi)的initialize函數(shù)只會(huì)調(diào)用一次,如果需要實(shí)現(xiàn)獨(dú)立的class和category的初始化就需要實(shí)現(xiàn)load函數(shù)。還需要注意的一點(diǎn)就是,如果subClass沒(méi)有實(shí)現(xiàn)initialize函數(shù),則父類(lèi)的initialize函數(shù)會(huì)被調(diào)用兩次
由于initialize函數(shù)可能會(huì)被調(diào)用多次,所以,如果想保證initialize函數(shù)只被調(diào)用一次,蘋(píng)果建議這樣做:

+(void)initialize {
  if (self == [className self]) { // ... do the initialization ... }
}

3.initialize函數(shù)的使用場(chǎng)景

initialize是線(xiàn)程安全的,有可能阻塞線(xiàn)程,所以,initialize函數(shù)應(yīng)該限制做一些簡(jiǎn)單,不復(fù)雜的類(lèi)初始化的前期準(zhǔn)備工作。
initialize函數(shù)的工作相當(dāng)簡(jiǎn)單,就是發(fā)送消息,這是和load函數(shù)實(shí)現(xiàn)不一樣的地方,load函數(shù)的調(diào)用直接是函數(shù)指針的調(diào)用,而initialize函數(shù)是消息的轉(zhuǎn)發(fā)。所以,class的子類(lèi)就算沒(méi)有實(shí)現(xiàn)initialize函數(shù),也會(huì)調(diào)用父類(lèi)的initialize函數(shù),如果子類(lèi)實(shí)現(xiàn)了initialize函數(shù),則子類(lèi)不會(huì)調(diào)用父類(lèi)的initialize函數(shù)。

總結(jié)

1.load在被添加到runtime的時(shí)候加載,initialize是類(lèi)第一次收到消息的時(shí)候被加載,load是在main函數(shù)之前,initialize是在main函數(shù)之后。

2.load方法的調(diào)用順序是:superClass -> class -> category;initialize方法的調(diào)用順序是:superClass -> class。都不需要顯示調(diào)用父類(lèi)的方法,系統(tǒng)會(huì)自動(dòng)調(diào)用,load方法是函數(shù)指針調(diào)用,initialize是發(fā)送消息。子類(lèi)如果沒(méi)有實(shí)現(xiàn)load函數(shù),子類(lèi)是不會(huì)調(diào)用父類(lèi)的load函數(shù)的,但是子類(lèi)沒(méi)有實(shí)現(xiàn)initialize函數(shù),則會(huì)調(diào)用父類(lèi)的initialize函數(shù)。

3.load和initialize內(nèi)部實(shí)現(xiàn)都加了線(xiàn)程鎖,是線(xiàn)程安全的,因此,這兩個(gè)函數(shù)應(yīng)該做一些簡(jiǎn)單的工作,不適合復(fù)雜的工作。

4.load函數(shù)通常用來(lái)進(jìn)行Method Swizzle,initialize函數(shù)則通常初始化一些全局變量,靜態(tài)變量。

參考:iOS基礎(chǔ)(九) - load和initialize的實(shí)現(xiàn)原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容