分享一些我对 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
已经被调用过了。