記錄一下load方法和initialize方法的區(qū)別和用法。參考的文獻(xiàn)分別是:
Stack Over:http://stackoverflow.com/questions/13326435/nsobject-load-and-initialize-what-do-they-do
簡(jiǎn)書:http://www.lxweimin.com/p/9368ce9bb8f9;
http://www.lxweimin.com/p/d25f691f0b07
1.load 方法的講解
(1)首先我們先看看Apple官方文檔的對(duì)load方法的描述
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
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:All initializers in any framework you link to.
All+loadmethods in your image.
All C++ static initializers and C/C++__attribute__(constructor)functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s+loadmethod is called after all of its superclasses’+loadmethods.
A category+loadmethod is called after the class’s own+loadmethod.
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.
其實(shí)我對(duì)這篇中用橫線消除的部分也不是很了解。但是我們可以看看加粗的句子。第一句話說明了load被調(diào)用的時(shí)機(jī)。也就是一個(gè)類或者分類被加入到runtime中的時(shí)候load方法就會(huì)被系統(tǒng)自動(dòng)調(diào)用??墒怯幸粋€(gè)問題,項(xiàng)目中含有很多類或者分類,那么A類的load方法和B類的load方法那個(gè)應(yīng)該被調(diào)用呢?在Xcode中有一個(gè)地方標(biāo)志了那個(gè)文件應(yīng)該先被調(diào)用load方法:
在compile sources中文件從上倒下的順序制定了調(diào)用load方法,當(dāng)然你可以手動(dòng)的更改文件load的順序通過調(diào)換compile sources中文件的順序。但是這個(gè)不是唯一的順序。請(qǐng)不要忘記了Apple文檔中說的那兩句話(我加粗的下面那兩句),在此基礎(chǔ)上應(yīng)該先調(diào)用父類,在調(diào)用子類。最后調(diào)用分類。
注意事項(xiàng):
1.load方法中可以不寫 [super load]; 系統(tǒng)會(huì)自動(dòng)幫你調(diào)用父類的方法。如果你寫了這句話那么系統(tǒng)會(huì)調(diào)用兩次哦。
2.load方法只能被調(diào)用一次。
(2)用途
2.1首先load方法是線程安全的。在load方法中不要使用鎖機(jī)制。如果在load方法中發(fā)生現(xiàn)成阻塞那么App加載開啟會(huì)非常慢,你可以在一個(gè)類的load方法中加入這句話sleep(10);線程睡10秒,那么你的啟動(dòng)頁(yè)面會(huì)停留10左右。
2.2可以在方法中對(duì)class文件進(jìn)行修改,例如調(diào)換方法實(shí)現(xiàn)。
2.Initialize方法講解
(1)文檔描述
Initializes the class before it receives its first message.
The runtime sends initialize to each class in a program just before the class, or any class that inherits from it, is sent its first message from within the program. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses. The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementation—or if subclasses explicitly call[super initialize]. If you want to protect yourself from being run multiple times, you can structure your implementation along these lines:
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
Because initialize is called in a thread-safe manner and the order of initialize being called on different classes is not guaranteed, it’s important to do the minimum amount of work necessary in initialize methods. Specifically, any code that takes locks that might be required by other classes in their initialize methods is liable to lead to deadlocks. Therefore you should not rely on initialize for complex initialization, and should instead limit it to straightforward, class local initialization.
initialize is invoked only once per class. If you want to perform independent initialization for the class and for categories of the class, you should implement?load?methods.
我們現(xiàn)在根據(jù)文檔看看initialize是什么含義。
1.1initialize什么時(shí)候會(huì)被調(diào)用,根據(jù)加粗的第一句話,我們可以知道runtime會(huì)在本身或者其子類在被第一次接收到消息(allocWithZone)的時(shí)候,initialize就會(huì)被發(fā)送給我們。當(dāng)其子類被調(diào)用的時(shí)候父類的也會(huì)被調(diào)用,這時(shí)候如果生成一個(gè)父類,那么父類的initialize就不會(huì)被調(diào)用,那是因?yàn)楦割愐呀?jīng)被調(diào)用過了,但是如果你要alloc一個(gè)父類的另一個(gè)子類,并且這個(gè)子類沒有重寫initialize那么意味著父類也會(huì)被調(diào)用一次。也就是說子類的initialize是在整個(gè)程序中只會(huì)調(diào)用一次,但是父類可能會(huì)被調(diào)用多次。這也就是為什么父類中initialize會(huì)被加入一個(gè)IF
1.2為什么要加入這個(gè)IF呢?self == [ClassName self]。因?yàn)楦割惖膇nitialize可能會(huì)被調(diào)用多次,那么加入這一話是為了保護(hù)我們自己制定的類要調(diào)用的code。我感覺我理解的不深刻,如果那位大神知道請(qǐng)指點(diǎn)。
1.3第三部分加粗,翻譯成如果想讓分類和本類的initialize都會(huì)被調(diào)用那么你必須在每個(gè)分類和本類中重寫load方法。關(guān)于分類我在后面給大家講解
(2)用途
作用就是可以在initialze方法中初始化一個(gè)寫static變量,我們知道如果你在一個(gè).m文件中給一個(gè)static變量賦值這是不允許的,編譯會(huì)報(bào)錯(cuò)。
3.initialize在分類中的反應(yīng)
有一個(gè)Teacher類,
+(void)initialize {
NSLog(@"%s",__func__);
}
Teacher有兩個(gè)分類分別是
@implementationTearch (Category)
+ (void)initialize {
NSLog(@"category");
}
@end
@implementationTearch (Zhao)
+ (void)initialize {
NSLog(@"Zhao");
}
@end
當(dāng)對(duì)Teacher進(jìn)行alloc的時(shí)候,控制臺(tái)打印出來的是
2016-08-30 22:24:01.803 load & initialize[23691:1040682] Zhao
可以看出來只能運(yùn)行一個(gè)initilaze,那么為什么有兩個(gè)問題(1)本類和分類比先運(yùn)行分類嗎?(2)兩個(gè)分類為什么先運(yùn)行(Zhao)呢?有什么依據(jù)嗎?
解答上面的問題:首先說說我們?nèi)绾蝸頊y(cè)試這個(gè)問題,就是我們?cè)谏厦鎐ompile source中來調(diào)用Tearch 和Tearch 分類的先后順序。我們得到了結(jié)論:
分類的優(yōu)先級(jí)要比本類高,有分類執(zhí)行分類
分類之間的優(yōu)先級(jí)根據(jù)compile source 中那個(gè)分類在上面反而沒有被執(zhí)行。
(3)根據(jù)文檔來看看重寫load方法讓他們都可以每一個(gè)initialzie都運(yùn)行。但是我給他們都加上load方法依然執(zhí)行了分類的initialize。希望大神指點(diǎn)。當(dāng)然在后面的研究里面如果我知道我也會(huì)更新我的文章希望大家諒解
4.load在分類中
每一個(gè)本類和分類都運(yùn)行l(wèi)oad方法
5.總結(jié)
5.1load方法是在main方法執(zhí)行之前,initialize是在main方法之后,由此我們可以知道load方法中沒有什么autorelease runloop。
5.2load方法適合做一些方法實(shí)現(xiàn)的替換。不適合生成一些變量。做很復(fù)雜的事情
5.3initialize方法適合進(jìn)行一寫static變量的初始化