iOS +(void)load運(yùn)行流程解析和運(yùn)用總結(jié)

最近因?yàn)闄C(jī)緣巧合接觸到了+(void)load方法,通過查看了幾篇博客,對load方法有了一定的認(rèn)識,今天通過該文章對該方法進(jìn)行一些小總結(jié)。


鎮(zhèn)樓圖.jpeg

+(void)load

官方是這么定義+(void)load方法的

Discussion
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
1.All initializers in any framework you link to.
2.All +load methods in your image.(這個image指的就是二進(jìn)制可執(zhí)行文件)
3.All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
4.All initializers in frameworks that link to you.
In addition:
1.A class’s +load method is called after all of its superclasses’ +load methods.
2.A category +load method is called after the class’s own +load method.
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.

由此我們可以知道load函數(shù)是只要你動態(tài)加載或者靜態(tài)引用了這個類,那么load就會被執(zhí)行,它并不需要你顯示的去創(chuàng)建一個類后才會執(zhí)行,同時只執(zhí)行一次。

另外就是關(guān)于load的執(zhí)行順序問題,所有的superclass的load執(zhí)行完以后才會執(zhí)行該類的load,以及class中的load方法是先于category中的load執(zhí)行的。

關(guān)于在category中l(wèi)oad方法的執(zhí)行使用,在iOS黑魔法-Method Swizzling中有很好的運(yùn)用例子。

運(yùn)行流程

通過前文對load方法的解釋,load方法是會加載所有的superclass后才會加載該類的load,最后加載該類的畫category。那么一個工程中有多不同的類那么load方法的執(zhí)行順序又是什么樣的呢?


測試工程類demo.png

如上圖我創(chuàng)建的測試工程中有如下幾個類

  • FatherClass
  • SonClass
  • SonClass+Load
  • FatherView

爸爸兒子也都有了,廢話不多說工程跑起來,斷點(diǎn)打起來吧~
經(jīng)過一陣斷點(diǎn)測試,工程是這么走的
FatherClass -> SonClass -> FatherView -> SonClass+Load
通過這個順序,確實(shí)是可以得出load方法在執(zhí)行中,會先執(zhí)行父類的方法,然后再執(zhí)行子類的方法,最后執(zhí)行了category的結(jié)論,當(dāng)然前提是load方法需要在類中實(shí)現(xiàn)。但是FatherView的load方法比SonClass+Load中的先執(zhí)行了,應(yīng)該是因?yàn)镕atherView即和其他的類沒有繼承關(guān)系,類型也不相同,在加載的時候是屬于同一優(yōu)先級,異步加載的情況下就比SonClass+Load先執(zhí)行了。

然后繼續(xù)測試玩一下,我在測試工程的main方法里打了斷點(diǎn),又在appdelegate的didFinishLaunchingWithOptions方法上打了斷點(diǎn)。


測試工程斷點(diǎn)圖.png

斷點(diǎn)也都有了,繼續(xù)跑一篇我們的工程~
然后就有了這樣的執(zhí)行順序

FatherClass -> SonClass -> SonClass+Load -> main -> appdelegate

load方法的對應(yīng)的類只要是引入了,并且該類實(shí)現(xiàn)了load方法,在main函數(shù)執(zhí)行之前就會一一執(zhí)行各類的load方法,load方法的執(zhí)行優(yōu)先級還是非常高的,因?yàn)閳?zhí)行在main函數(shù)之前,所以千萬不要在這里初始化OC的對象,因?yàn)閘oad執(zhí)行的時候你不知道你使用的對象是否已經(jīng)被加載進(jìn)來,所以無法預(yù)知情況。

運(yùn)用

從上文的運(yùn)行流程分析中已經(jīng)了解到,main函數(shù)是整個應(yīng)用運(yùn)行的入口load方法是在main函數(shù)之前執(zhí)行的,并且只執(zhí)行一次,load方法既然這么特殊,那么在使用他時肯定還是要注意很多東西。

  • 不要做耗時操作
    因?yàn)閳?zhí)行在main函數(shù)之前,所有是所有實(shí)現(xiàn)的load函數(shù)跑完了才會啟動應(yīng)用,在load方法中進(jìn)行耗時操作必然會影響程序的啟動時間,這么一想load方法里寫耗時操作一聽就是大忌了。比如下面的騷操作···
+ (void)load {
    for (NSInteger i = 0; i < 10000; i ++) {
        NSLog(@"%zd" , i);
    }
}
  • 不要做對象的初始化操作
    因?yàn)樵趍ain函數(shù)之前自動調(diào)用,load方法調(diào)用的時候使用者根本就不能確定自己要使用的對象是否已經(jīng)加載進(jìn)來了,所以千萬不能在這里初始化對象。

  • 常用場景 load方法中實(shí)現(xiàn)Method Swizzle
    Method Swizzing是發(fā)生在運(yùn)行時的,主要用于在運(yùn)行時將兩個Method進(jìn)行交換,我們可以將Method Swizzling代碼寫到任何地方,但是只有在這段Method Swilzzling代碼執(zhí)行完畢之后互換才起作用。

+ (void)load {
    Method originalFunc = class_getInstanceMethod([self class], @selector(originalFunc));
    Method swizzledFunc = class_getInstanceMethod([self class], @selector(swizzledFunc));
    method_exchangeImplementations(originalFunc, swizzledFunc);
}

在load方法中使用Method Swizzle 是一個常用場景。

此篇博客中參考了其他幾個博主的一些知識點(diǎn),自己做了一些實(shí)驗(yàn)證實(shí)和總結(jié),全當(dāng)是加深自己印象的筆記,如果讀者有覺得不夠詳盡或者不夠明白的位置,可以參考下面幾個相關(guān)博客的內(nèi)容。
????????
相關(guān)博客:
NSObject中+(void)load運(yùn)行流程解析
細(xì)說OC中的load和initialize方法
iOS黑魔法-Method Swizzling

最后分享一下家里的小喵~


么么噠.jpeg

吸一口,精神抖擻!

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

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

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