記錄一下load方法和initialize方法的區(qū)別和用法。參考的文獻分別是:
Stack Over:http://stackoverflow.com/questions/13326435/nsobject-load-and-initialize-what-do-they-do
簡書:http://www.reibang.com/p/9368ce9bb8f9诡延;
http://www.reibang.com/p/d25f691f0b07
1.load 方法的講解
(1)首先我們先看看Apple官方文檔的對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.
其實我對這篇中用橫線消除的部分也不是很了解鱼的。但是我們可以看看加粗的句子悠轩。第一句話說明了load被調用的時機。也就是一個類或者分類被加入到runtime中的時候load方法就會被系統自動調用。可是有一個問題时肿,項目中含有很多類或者分類,那么A類的load方法和B類的load方法那個應該被調用呢糟秘?在Xcode中有一個地方標志了那個文件應該先被調用load方法:
在compile sources中文件從上倒下的順序制定了調用load方法区匣,當然你可以手動的更改文件load的順序通過調換compile sources中文件的順序。但是這個不是唯一的順序炭分。請不要忘記了Apple文檔中說的那兩句話(我加粗的下面那兩句)桃焕,在此基礎上應該先調用父類,在調用子類捧毛。最后調用分類观堂。
注意事項:
1.load方法中可以不寫 [super load]; 系統會自動幫你調用父類的方法。如果你寫了這句話那么系統會調用兩次哦呀忧。
2.load方法只能被調用一次师痕。
(2)用途
2.1首先load方法是線程安全的。在load方法中不要使用鎖機制而账。如果在load方法中發(fā)生現成阻塞那么App加載開啟會非常慢胰坟,你可以在一個類的load方法中加入這句話sleep(10);線程睡10秒泞辐,那么你的啟動頁面會停留10左右笔横。
2.2可以在方法中對class文件進行修改竞滓,例如調換方法實現。
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.
我們現在根據文檔看看initialize是什么含義吹缔。
1.1initialize什么時候會被調用商佑,根據加粗的第一句話,我們可以知道runtime會在本身或者其子類在被第一次接收到消息(allocWithZone)的時候厢塘,initialize就會被發(fā)送給我們茶没。當其子類被調用的時候父類的也會被調用,這時候如果生成一個父類晚碾,那么父類的initialize就不會被調用抓半,那是因為父類已經被調用過了,但是如果你要alloc一個父類的另一個子類格嘁,并且這個子類沒有重寫initialize那么意味著父類也會被調用一次笛求。也就是說子類的initialize是在整個程序中只會調用一次,但是父類可能會被調用多次讥蔽。這也就是為什么父類中initialize會被加入一個IF
1.2為什么要加入這個IF呢涣易?self == [ClassName self]。因為父類的initialize可能會被調用多次冶伞,那么加入這一話是為了保護我們自己制定的類要調用的code新症。我感覺我理解的不深刻,如果那位大神知道請指點响禽。
1.3第三部分加粗徒爹,翻譯成如果想讓分類和本類的initialize都會被調用那么你必須在每個分類和本類中重寫load方法。關于分類我在后面給大家講解
(2)用途
作用就是可以在initialze方法中初始化一個寫static變量芋类,我們知道如果你在一個.m文件中給一個static變量賦值這是不允許的隆嗅,編譯會報錯。
3.initialize在分類中的反應
有一個Teacher類侯繁,
+(void)initialize {
NSLog(@"%s",__func__);
}
Teacher有兩個分類分別是
@implementationTearch (Category)
+ (void)initialize {
NSLog(@"category");
}
@end
@implementationTearch (Zhao)
+ (void)initialize {
NSLog(@"Zhao");
}
@end
當對Teacher進行alloc的時候胖喳,控制臺打印出來的是
2016-08-30 22:24:01.803 load & initialize[23691:1040682] Zhao
可以看出來只能運行一個initilaze,那么為什么有兩個問題(1)本類和分類比先運行分類嗎贮竟?(2)兩個分類為什么先運行(Zhao)呢丽焊?有什么依據嗎?
解答上面的問題:首先說說我們如何來測試這個問題咕别,就是我們在上面compile source中來調用Tearch 和Tearch 分類的先后順序技健。我們得到了結論:
分類的優(yōu)先級要比本類高,有分類執(zhí)行分類
分類之間的優(yōu)先級根據compile source 中那個分類在上面反而沒有被執(zhí)行惰拱。
(3)根據文檔來看看重寫load方法讓他們都可以每一個initialzie都運行雌贱。但是我給他們都加上load方法依然執(zhí)行了分類的initialize。希望大神指點。當然在后面的研究里面如果我知道我也會更新我的文章希望大家諒解
4.load在分類中
每一個本類和分類都運行l(wèi)oad方法
5.總結
5.1load方法是在main方法執(zhí)行之前欣孤,initialize是在main方法之后馋没,由此我們可以知道load方法中沒有什么autorelease runloop。
5.2load方法適合做一些方法實現的替換导街。不適合生成一些變量披泪。做很復雜的事情
5.3initialize方法適合進行一寫static變量的初始化