+load和+initialize

来源:互联网 发布:阿玛拉王国 mac 下载 编辑:程序博客网 时间:2024/06/02 04:50

一、load初探

1、介绍

先看看 NSObject Class Reference 中关于 + (void)load 的说明:

DiscussionThe 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.

从上面的描述可以看出:

1、+ (void)load 会在类或者类的分类添加到 Objective-c runtime 时调用,该调用发生在 application:willFinishLaunchingWithOptions: 调用之前调用。
2、父类的 +load 方法先于子类的 +load 方法调用,类本身的 +load 方法先于分类的 +load 方法调用。

2、实例

例如:

@implementation Person+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end@implementation Child+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end
@implementation Person (personLoad)+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end
@implementation Child (childLoad)+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end

打印:

2016-08-25 17:09:07.905 load[40236:683579] Person   +[Person load]2016-08-25 17:09:07.906 load[40236:683579] Child   +[Child load]2016-08-25 17:09:07.907 load[40236:683579] Person   +[Person(personLoad) load]2016-08-25 17:09:07.907 load[40236:683579] Child   +[Child(childLoad) load]

二、initialize初探

1、介绍

先看看 NSObject Class Reference 中关于 +initialize 的说明:

Initializes the class before it receives its first message.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. The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses. 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:12345+ (void)initialize {  if (self == [ClassName self]) {    // ... do the initialization ...  }}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、+ (void)initialize 消息是在该类接收到其第一个消息之前调用。关于这里的第一个消息需要特别说明一下,对于 NSObject 的 runtime 机制而言,其在调用 NSObject 的 + (void)load 消息不被视为第一个消息,但是,如果像普通函数调用一样直接调用 NSObject 的 + (void)load 消息,则会引起 + (void)initialize 的调用。反之,如果没有向 NSObject 发送第一个消息,+ (void)initialize 则不会被自动调用。
2、在应用程序的生命周期中,runtime 只会向每个类发送一次 + (void)initialize 消息,如果该类是子类,且该子类中没有实现 + (void)initialize 消息,或者子类显示调用父类实现 [super initialize], 那么则会调用其父类的实现。也就是说,父类的 + (void)initialize 可能会被调用多次。
3、如果类包含分类,且分类重写了initialize方法,那么则会调用分类的 initialize 实现,而原类的该方法实现不会被调用,这个机制同 NSObject 的其他方法(除 + (void)load 方法) 一样,即如果原类同该类的分类包含有相同的方法实现,那么原类的该方法被隐藏而无法被调用。
4、父类的 initialize 方法先于子类的 initialize 方法调用。

2、实例

Child* child = [[Child alloc]init];@implementation Person+ (void)initialize{    NSLog(@"%@   %s", [self class],__FUNCTION__);}+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end@implementation Child+ (void)initialize{    NSLog(@"%@   %s", [self class],__FUNCTION__);}+ (void)load{    NSLog(@"%@   %s", [self class],__FUNCTION__);}@end

打印:

2016-08-25 17:39:12.473 load[40474:703111] Person   +[Person initialize]2016-08-25 17:39:12.475 load[40474:703111] Person   +[Person load]2016-08-25 17:39:12.475 load[40474:703111] Child   +[Child initialize]2016-08-25 17:39:12.475 load[40474:703111] Child   +[Child load]

上面示例可以看出子类会调用父类的 + initialize 方法。

三、比较

1、 load和initialize的共同特点

  • (1)、在不考虑开发者主动使用的情况下,系统最多会调用一次
  • (2)、如果父类和子类都被调用,父类的调用一定在子类之前
  • (3)、都是为了应用运行提前创建合适的运行环境
  • (4)、在使用时都不要过重地依赖于这两个方法,除非真正必要

2、load方法相关要点

  • (1)、调用时机比较早,运行环境有不确定因素。具体说来,在iOS上通常就是App启动时进行加载,但当load调用的时候,并不能保证所有类都加载完成且可用,必要时还要自己负责做auto release处理。
  • (2)、补充上面一点,对于有依赖关系的两个库中,被依赖的类的load会优先调用。但在一个库之内,调用顺序是不确定的。
    对于一个类而言,没有load方法实现就不会调用,不会考虑对NSObject的继承。
  • (3)、一个类的load方法不用写明[super load],父类就会收到调用,并且在子类之前。
    Category的load也会收到调用,但顺序上在主类的load调用之后。
  • (4)、不会直接触发initialize的调用。

3、initialize方法相关要点

  • (1)、initialize的自然调用是在第一次主动使用当前类的时候(lazy,这一点和Java类的“clinit”的很像)。
  • (2)、在initialize方法收到调用时,运行环境基本健全。
  • (3)、initialize的运行过程中是能保证线程安全的。
  • (4)、和load不同,即使子类不实现initialize方法,会把父类的实现继承过来调用一遍。注意的是在此之前,父类的方法已经被执行过一次了,同样不需要super调用。
0 0
原创粉丝点击