load和initialize

一:  load、initialize方法的區(qū)別什么?
1. 調(diào)用方式
  1> load是根據(jù)函數(shù)地址直接調(diào)用
  2> initialize是通過(guò)objc_msgSend調(diào)用
2. 調(diào)用時(shí)刻
  1> Load是runtime加載類、分類的時(shí)候調(diào)用(只會(huì)調(diào)用1次)
  2> initialize是類第一次接收到消息的時(shí)候調(diào)用,每一個(gè)類只會(huì)initialize一次(父類的initialize方法可能
會(huì)被調(diào)用多次)

二:  load、initialize的調(diào)用順序?
1. load
    1> 先調(diào)用類的load
      a) 先編譯的類,優(yōu)先調(diào)用load
      b) 調(diào)用子類的load之前,會(huì)先調(diào)用父類的load

  2> 再調(diào)用分類的load
     a) 先編譯的分類,優(yōu)先調(diào)用load

2. initialize
1> 先初始化父類
2> 再初始化父類
image.png
  1. 調(diào)用順序
    以main為分界,load方法在main函數(shù)之前執(zhí)行,initialize在main函數(shù)之后執(zhí)行

  2. 相同點(diǎn)和不同點(diǎn)
    2.1 相同點(diǎn)
    load和initialize會(huì)被自動(dòng)調(diào)用,不能手動(dòng)調(diào)用它們。
    子類實(shí)現(xiàn)了load和initialize的話,會(huì)隱式調(diào)用父類的load和initialize方法
    load和initialize方法內(nèi)部使用了鎖,因此它們是線程安全的。
    2.2 不同點(diǎn)
    子類中沒(méi)有實(shí)現(xiàn)load方法的話,不會(huì)調(diào)用父類的load方法;而子類如果沒(méi)有實(shí)現(xiàn)initialize方法的話,也會(huì)自動(dòng)調(diào)用父類的initialize方法。
    load方法是在類被裝在進(jìn)來(lái)的時(shí)候就會(huì)調(diào)用,initialize在第一次給某個(gè)類發(fā)送消息時(shí)調(diào)用(比如實(shí)例化一個(gè)對(duì)象),并且只會(huì)調(diào)用一次,是懶加載模式,如果這個(gè)類一直沒(méi)有使用,就不回調(diào)用到initialize方法。

  3. load
    在執(zhí)行l(wèi)oad方法之前,會(huì)調(diào)用load_images方法,用來(lái)掃描鏡像中的+ load符號(hào),將需要調(diào)用 load 方法的類添加到一個(gè)列表中l(wèi)oadable_classes,在這個(gè)列表中,會(huì)先把父類加入到待加載列表,這樣保證父類在父類在子類錢調(diào)用load方法,而分類中的load方法會(huì)在類的load的方法后面加入另外一個(gè)待加載列表loadable_categories,這樣保證了兩個(gè)規(guī)則:

父類先于子類調(diào)用
類先于分類調(diào)用
在掃描完load方法加入到待加載方法后,會(huì)調(diào)用call_load_methods,先從loadable_classes調(diào)用類的load方法,call_class_loads;調(diào)用完loadable_classes后會(huì)調(diào)用loadable_categories中分類的load方法,call_category_loads。

調(diào)用順序如下:

父類load先于類添加到loadable_classes列表,通過(guò)call_class_loads,調(diào)用列表中的load方法,這樣父類的load先于類的load執(zhí)行
當(dāng)loadable_classes為空的時(shí)候,查看loadable_classes是否為空,如果不為空則調(diào)用call_category_loads加載分類中的load方法,這樣分類的load在類之后執(zhí)行

  1. initialize
    initialize 只會(huì)在對(duì)應(yīng)類的方法第一次被調(diào)用時(shí),才會(huì)調(diào)用,initialize 方法是在 alloc 方法之前調(diào)用的,alloc 的調(diào)用導(dǎo)致了前者的執(zhí)行。

initialize的調(diào)用棧中,直接調(diào)用其方法的其實(shí)是_class_initialize 這個(gè)C語(yǔ)言函數(shù),在這個(gè)方法中,主要是向?yàn)槌跏蓟念惏l(fā)送+initialize消息,不過(guò)會(huì)強(qiáng)制父類先發(fā)送。

與 load 不同,initialize 方法調(diào)用時(shí),所有的類都已經(jīng)加載到了內(nèi)存中。

  1. 使用場(chǎng)景
    5.1 load
    load一般是用來(lái)交換方法Method Swizzle,由于它是線程安全的,而且一定會(huì)調(diào)用且只會(huì)調(diào)用一次,通常在使用UrlRouter的時(shí)候注冊(cè)類的時(shí)候也在load方法中注冊(cè)

5.2 initialize
initialize方法主要用來(lái)對(duì)一些不方便在編譯期初始化的對(duì)象進(jìn)行賦值,或者說(shuō)對(duì)一些靜態(tài)常量進(jì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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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