?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)代碼。
?
?