分享一些我對 NSObject
的 +load
方法的一些理解。安全
在每一個類和類別初始化的時候都會調用,子類不會重載父類的 +load
,兩個都會調用這個方法。async
各個 +load
方法遵照蘋果文檔所說的順序:函數
The order of initialization is as follows:oop
- All initializers in any framework you link to.
- All
+load
methods 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:ui
A class’s
+load
method is called after all of its superclasses’+load
methods.
A category+load
method is called after the class’s own +load method.spa
可是官方的說明不是很完整,因而我用 Xcode 驗證了一下,這裏是一些驗證結果:設計
咱們本身鏈接的靜態庫,包括僞 framework(本質上是個靜態庫),實際上也屬於蘋果文檔裏說的 your image。也就是說,若是裏面有實現 load 方法的類,不能保證它們老是先調用。通常來講是這樣的順序:code
+load
。+load
。+load
。+load
。可是若是繼承了來自靜態庫的類,那麼按照蘋果的規則,他們的父類會提早調用 +load
。沒有繼承關係的類之間,+load
的調用順序跟隨編譯順序。編譯順序能夠在 target 的 Build Phases 裏面指定。類別之間,調用 +load
的順序也是徹底按照編譯順序。繼承
假設類 A 和類 B 都是咱們的項目裏的類。若是咱們想在 A 調用 +load
的時候發消息給 B,能夠嗎?事件
答案是:能夠的,可是不能直接發消息給 B。爲何呢?若是直接發消息給 B ,由於不知道 B 是否必定要調用 +load
才能用,因此頗有可能會出錯。並且這樣會致使 B 的 +initialize
在 +load
以前就調用了,也許會破壞了 B 的設計者的本意。
正確的方法應該是,等待當前的初始化函數結束了,再發消息給 B。用 GCD 來實現的話,就是這樣寫:
{% codeblock 安全方法 lang:objc %}
dispatch_async(dispatch_get_main_queue(), ^{
[B doSomthing];
});
{% endcodeblock %}
這樣寫之因此是對的,是由於這樣不會立刻調用 B 的 +doSomthing
方法,而是等到 RunLoop 下一次事件開始再調用。那時候整個初始化已經結束了,這樣就能確保 B 的 +load
已經被調用過了。