这篇水文主要是昨晚无意看到网上有些关于这个问题,却瞎写的。后面还一群评论求带飞。。。。。别误人子弟好么
+ (void)load
第一,先看苹果爸爸的文档
https://developer.apple.com/documentation/objectivec/nsobject/1418815-load?language=objc
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不同于普通方法,系统在调用时候,子类重写不会影响父类的方法,分类也不会影响主类的方法。也就是各有个的,互不影响。
此外,load方法是在加载image的时候调用的,比main方法还前,不用在这里做耗时操作。
可以在Xcode中加入 OBJC_PRINT_LOAD_METHODS
并设置为 YES 后,将会打印出很多 +load
方法执行时的信息。
+ (void)initialize
先附上苹果爸爸的文档
https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?language=occ
Discussion
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 ... } }
有几点要留意:
1、在首次用到这个类或这个类的子类的时候,会调用initialize
。所以如果某个类一直没用到,那么initialize
就不会被调用。
2、每个类只会调用一次。(这里所说的每个类,指的是以类名作为区分,分类和主类算同一个类。但是子类和父类算不同类)如果分类和主类都写了initialize
。只会调用分类的。如果有多个分类都复写了,调用的是在编译顺序最后的一个分类的。
3、如果子类没有复写initialize
,那子类调用的时候就会按照父类的逻辑进行调用,意思是:当父类有分类复写initialize
,那么调用父类分类的initialize
,否则调用父类的initialize
。所以这里可能会导致父类的initialize
被调用多次。
总结
1、能不用load
,就不用,尽量都放到initialize
去做。因为这个load
会拖慢应用启动。
2、initialize
注意会被多次调用,且会受到分类的复写影响。
网友评论