iOS 中 initialize 與 load 兩個“類的初始化方法”特性

?load 方法,其原型如下:

? +(void)load;

?? 對于加入運行期系統(tǒng)中的每個類及分類來說,必定會調(diào)用此方法,而且僅調(diào)用一次。如果分類和其所屬的類都定義了load方法,則先調(diào)用類里的,在調(diào)用分類的。

?? load方法的問題在于,執(zhí)行該方法時,運行期系統(tǒng)處于“脆弱狀態(tài)”。在執(zhí)行子類的load方法之前,必定會先執(zhí)行所有超類的load方法,而如果代碼還依賴了其他程序庫,那么程序庫里相關(guān)類的load方法也必定會先執(zhí)行。然而,根據(jù)某個給定的程序庫,卻無法判斷出其中各個類的載入順序。因此,在load方法中使用其他類是不安全的。如下斷代碼:

?? #import <Foundation/Foundation.h>

?? #import "ClassA.h"

?? @interface ClassB : NSObject

?? @end

?? @implementation ClassB

?? +(void)load {

?????? NSLog(@"Loading ClassB");

?????? ClassA *object = [ClassA new];

?? }

?? @end

? 此處使用NSLog沒有問題,而且相關(guān)字符串也會照常記錄,因為Foundation框架肯定在運行l(wèi)oad方法之前就已經(jīng)載入系統(tǒng)了。但是,在ClassB的load方法里使用ClassA卻不太安全,因為無法確定在執(zhí)行ClassB的load方法之前,ClassA是不是加載好了。

? 還有一點需要注意的是,load方法并不想普通方法那樣,它并不遵從繼承規(guī)則。如果某各類本身沒有實現(xiàn)load方法,那么不管其各超類是否實現(xiàn)此方法,系統(tǒng)都不會調(diào)用。此外,分類和其所屬的類里,都可能出現(xiàn)load方法。此時兩種實現(xiàn)代碼都會調(diào)用,類的實現(xiàn)要比分類的實現(xiàn)先調(diào)用。

? 整個應(yīng)用在執(zhí)行l(wèi)oad方法是都會阻塞,如果load方法中包含繁雜的代碼,那么應(yīng)用程序在執(zhí)行期間就會變得無響應(yīng)。不要在里面等待鎖,也不要調(diào)用可能會加鎖的方法。總之,能不做的事情就別做。其真正的用途僅在于調(diào)試程序,比如可以在分類里編寫此方法,用來判斷該分類是否已經(jīng)正確加載。

? 想要執(zhí)行與類相關(guān)的初始化操作,還有個辦法,就是覆寫 +(void)initialize;

? 該方法會在程序首次用該類之前調(diào)用,且只調(diào)用一次。其雖與load方法類似,但卻有幾個非常重要的微妙區(qū)別:首先,它是“惰性調(diào)用的”,應(yīng)用程序無須把每個類的initialize方法都執(zhí)行一遍,這與load方法不同,對于load來說,應(yīng)用程序必須阻塞等著所有的類的load都執(zhí)行完,才能繼續(xù)。其次,運行期系統(tǒng)在執(zhí)行該方法是,是處于正常狀態(tài)的,運行期系統(tǒng)也能確保initialize方法一定會在“線程安全的環(huán)境”中執(zhí)行,這就是說,只有執(zhí)行initialize的那個線程可以操作類或類實例,其他線程都要先阻塞,等著initialize執(zhí)行完。最后,initialize方法與其他消息一樣,如果某個類未實現(xiàn)它,而其超類實現(xiàn)了,那么就會運行超類的實現(xiàn)代碼。

?

?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容