+(void)load与+(void)initialize区别
对+load的理解
首先在官方的文档中这么定义的load函数的:
Discussion
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
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:
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.
In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.
由此我们可以知道load函数只要你动态加载或者静态引用了这个类,那么load就会被执行,它并不需要你显式的去创建一个类后才会执行,同时只执行一次。
它只是一个在整个文件被加载到运行时,在main函数调用之前ObjC运行时调用的钩子方法。
另外就是关于load的执行顺序问题。所有的superclass的load执行完以后才会至此那个该类的load,以及class中load方法是先与category中的load执行的。
参考资料:
对+initialize的理解
同理,先上initialize的官方描述:
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 implementation—or 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.
- initialize 是在当前类或者其子类通过runtime发送第一个消息之前调用。
+load与+initialize的比较
相同点:
- 在不考虑开发者主动使用的情况下,系统最多会调用一次。
- 如果父类和子类的方法都被调用,那么父类的调用一定在子类之前。
- 都是为了应用运行提前创建合适的运行环境
- 在使用时都不要过多地依赖于这两个方法,除非真正必要。
不同点:
+load 方法:
* 调用时机比较早,运行环境有不确定因素。因为load实在整个文件被加载到运行时时,在main函数调用之前被ObjC运行时调用的方法。当load调用的时候,并不能保证所有类都加载完成且可用,必要的时候还要自己负责auto release处理。
* 对于一个雷,如果没有实现load方法就不会被调用,不会考虑对NSObjet的继承。
* 父类的load方法会优先于子类调用,类别的load方法一般最后调用不会直接出发initialize的调用。
通俗的讲就是: 在程序启动之前会调用所有的类的(手动实现的)+load方法(没有实现就不调用咯),按(父类->子类->类别)的顺序调用.
+initialize方法:
- initialize的自然调用实在第一次主动使用当前类的时候被调用(第一次alloc时候)。
- 在initialize方法收到调用时,运行环建基本健全了。
- initialize的运行过程中是能够保证线程安全的。
- 和load不同,即时子类不能实现initialize犯法,会把父类的实现继承过来调用一遍。注意的是在此之前父类的方法已经被执行过一次了,同样不需要super调用。
通俗的讲就是:在程序启动之后,在第一次创建这个类的对象的时候(也就是分配内存空间alloc的时候),会调用该类的+initialize方法且只调用一次.
[调用顺序 1.如果父类的initialize方法没有被调用过会先调用父类的initialize方法) 2.如果该类有类别只会调用类别的+initialize(如果有多个类别会调用某一个类别的initialize方法,其他的不会调用)]
由于initialize的这些特点,使得其应用比load要略微广泛一些。可用来做一些初始化工作,或者单例模式的一种实现方案。
Apple的文档很清楚地说明了initialize和load的区别在于:load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。