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 已经被调用过了。

相关文章
相关标签/搜索