NSObject 的 load 方法

分享一些我對 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 已經被調用過了。

相關文章
相關標籤/搜索