load
+ (void)load;
對(duì)于加入運(yùn)行期系統(tǒng)的類及分類,必定會(huì)調(diào)用此方法,且僅調(diào)用一次。
iOS會(huì)在應(yīng)用程序啟動(dòng)的時(shí)候調(diào)用load方法倍啥,在main函數(shù)之前調(diào)用
執(zhí)行子類的load方法前,會(huì)先執(zhí)行所有超類的load方法澎埠,順序?yàn)楦割?>子類->分類
在load方法中使用其他類是不安全的,因?yàn)闀?huì)調(diào)用其他類的load方法始藕,而如果關(guān)系復(fù)雜的話蒲稳,就無法判斷出各個(gè)類的載入順序,類只有初始化完成后伍派,類實(shí)例才能進(jìn)行正常使用
load 方法不遵從繼承規(guī)則江耀,如果類本身沒有實(shí)現(xiàn)load方法,那么系統(tǒng)就不會(huì)調(diào)用诉植,不管父類有沒有實(shí)現(xiàn)(跟下文的initialize有明顯區(qū)別)
盡可能的精簡(jiǎn)load方法祥国,因?yàn)檎麄€(gè)應(yīng)用程序在執(zhí)行l(wèi)oad方法時(shí)會(huì)阻塞,即,程序會(huì)阻塞直到所有類的load方法執(zhí)行完畢舌稀,才會(huì)繼續(xù)
load 方法中最常用的就是方法交換method swizzling
initialize
+ (void)initialize;
在首次使用該類之前由運(yùn)行期系統(tǒng)(非人為)調(diào)用啊犬,且僅調(diào)用一次
惰性調(diào)用,只有當(dāng)程序使用相關(guān)類時(shí)壁查,才會(huì)調(diào)用
運(yùn)行期系統(tǒng)會(huì)確保initialize方法是在線程安全的環(huán)境中執(zhí)行觉至,即,只有執(zhí)行initialize的那個(gè)線程可以操作類或類實(shí)例睡腿。其他線程都要先阻塞语御,等待initialize執(zhí)行完
如果類未實(shí)現(xiàn)initialize方法,而其超類實(shí)現(xiàn)了席怪,那么會(huì)運(yùn)行超類的實(shí)現(xiàn)代碼应闯,而且會(huì)運(yùn)行兩次(load 第5點(diǎn))
initialize 遵循繼承規(guī)則
初始化子類的的時(shí)候會(huì)先初始化父類,然后會(huì)調(diào)用父類的initialize方法挂捻,而子類沒有覆寫initialize方法碉纺,因此會(huì)再次調(diào)用父類的實(shí)現(xiàn)方法
鑒于此,initialize方法實(shí)現(xiàn)如下:
+ (void)initialize {
if (self == [People class]) {
NSLog(@"%@ initialize", self);
}
}
initialize方法也需要盡量精簡(jiǎn)细层,一般只應(yīng)該用來設(shè)置內(nèi)部數(shù)據(jù)惜辑,比如,某個(gè)全局狀態(tài)無法在編譯期初始化疫赎,可以放在initialize里面盛撑。
static NSMutableArray *kSomeObjects;
@implementation People
+ (void)initialize {
if (self == [People class]) {
kSomeObjects = [NSMutableArray new];
}
}
總結(jié):
1. 在加載階段,如果類實(shí)現(xiàn)了load方法捧搞,系統(tǒng)就會(huì)調(diào)用它抵卫,load方法不參與覆寫機(jī)制
2. 在首次使用某個(gè)類之前,系統(tǒng)會(huì)向其發(fā)送initialize消息胎撇,通常應(yīng)該在里面判斷當(dāng)前要初始化的類介粘,防止子類未覆寫initialize的情況下調(diào)用兩次
3. load與initialize方法都應(yīng)該實(shí)現(xiàn)得精簡(jiǎn)一些,有助于保持應(yīng)用程序的響應(yīng)能力晚树,也能減少引入“依賴環(huán)”(interdependency cycle)的幾率
4. 無法在編譯期設(shè)定的全局常量姻采,可以放在initialize方法里初始化