0%

runtime +load与+initialize分析

通过一个简单的打印实验就可以发现:

  • +initialize方法和+load调用时机
  • +initialize在父类,子类,类别之间的关系
  • +load在父类,子类,类别之间的关系

如下表格:

+load +initialize
调用时机 被添加到 runtime 时(类被加载时) 第一次调用该类的类方法或实例方法前调用,可能永远不调用
调用顺序 父类->子类->分类(多个分类间,则按加载顺序) 父类->分类(多个分类时,是最后一个的被执行)or子类
是否需要显式调用父类实现
自身没实现是否调用父类的实现
分类中实现产生的影响 类和分类都执行 覆盖类中的方法,只执行分类的实现

另:Swizzling should always be done in +load.

initialize

文档说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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. Superclasses receive this message before their subclasses.

The runtime sends the initialize message to classes in a thread-safe manner. That is, initialize is run by the first thread to send a message to a class, and any other thread that tries to send a message to that class will block until initialize completes.

The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementationor 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 blocking manner, it’s important to limit method implementations to the minimum amount of work necessary possible. 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.

Special Considerations
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.

有几个点值得说一下:

1、initialize方法是线程安全的。当第一个线程触发initialize执行后,其他线程发送的消息都会被阻塞直到initialize执行完成。

2、父类的实现可能会被执行多次。有时候并不想initialize里的代码执行多次,建议使用dispatch_once保护起来。

3、initialize方法是以同步的方式执行的,所以里面的实现最好尽可能的简单。尤其是涉及到锁的逻辑就需要特别小心,处理不好可能会导致死锁。

参考:

Objective-C 深入理解 +load 和 +initialize

觉得文章有帮助可以打赏一下哦!