Objective-C 有两个神奇的方法:+load 和 +initialize,这两个方法在类被使用时会自动调用。但是两个方法的不同点会导致应用层面上性能的显著差异。
1.+ initialize 方法和+load 调用时机
1.1 + initialize 方法:
会在第一次初始化这个类之前被调用,我们用它来初始化静态变量。
1.2+ load 方法:
会在加载类的时候就被调用,也就是 ios 应用启动的时候,就会加载所有的类,就会调用每个类的 + load 方法。
2.实例
2.1 + load
#pragram ---main函数中的代码---
#import <UIKit/UIKit.h>
#import"AppDelegate.h"
int main(int argc, char * argv[]) {
NSLog(@"%s",__func__);
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
#pragram ---基于NSObject的Person类---
#import "Person.h"
@implementation Person
+ (void)load{
NSLog(@"%s",__func__);
}
+ (void)initialize{
[super initialize];
NSLog(@"%s %@",__func__,[self class]);
}
- (instancetype)init{
if (self = [super init]) {
NSLog(@"%s",__func__);
}
return self;
}
@end
#pragram ---基于Person的Girl类---
#import "Girl.h"
@implementation Girl
+ (void)load{
NSLog(@"%s ",__func__);
}
+ (void)initialize{
[super initialize];
NSLog(@"%s ",__func__);
}
- (instancetype)init{
if (self = [super init]) {
NSLog(@"%s",__func__);
} return self;
}
@end
输出日志如下:
2018-03-22 15:49:19.981240+0800 test[51130:1824513] +[Person load]
2018-03-22 15:49:19.981703+0800 test[51130:1824513] +[Girl load]
2018-03-22 15:49:19.981913+0800 test[51130:1824513] main
这说明在我并没有对类做任何操作的情况下,+load 方法会被默认执行,并且是在 main 函数之前执行的。
2.2 + initialize
#import "ViewController.h"
#import "Person.h"
#import "Girl.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Person * a = [Person new];
Person * b = [Person new];
Girl *c = [Girl new];
Girl *d = [Girl new];
}
@end
输出日志如下:
2018-03-22 15:51:50.257071+0800 test[51204:1827692] +[Person load]
2018-03-22 15:51:50.257721+0800 test[51204:1827692] +[Girl load]
2018-03-22 15:51:50.258080+0800 test[51204:1827692] main
2018-03-22 15:51:50.385627+0800 test[51204:1827692] +[Person initialize]--Person
2018-03-22 15:51:50.385776+0800 test[51204:1827692] -[Person init]
2018-03-22 15:51:50.385865+0800 test[51204:1827692] -[Person init]
2018-03-22 15:51:50.385976+0800 test[51204:1827692] +[Person initialize]--Girl
2018-03-22 15:51:50.386088+0800 test[51204:1827692] +[Girl initialize]
2018-03-22 15:51:50.386254+0800 test[51204:1827692] -[Person init]
2018-03-22 15:51:50.386362+0800 test[51204:1827692] -[Girl init]
2018-03-22 15:51:50.386497+0800 test[51204:1827692] -[Person init]
2018-03-22 15:51:50.386739+0800 test[51204:1827692] -[Girl init]
通过这个实验我们可以确定两点:
- initialize 方法类似一个懒加载,如果没有使用这个类,那么系统默认不会去调用这个方法,且默认只加载一次;
- initialize 的调用发生在 +init 方法之前。
3.总结
如果你实现了 + load 方法,那么当类被加载时它会自动被调用。这个调用非常早。如果你实现了一个应用或框架的 + load,并且你的应用链接到这个框架上了,那么 + load 会在 main() 函数之前被调用。如果你在一个可加载的 bundle 中实现了 + load,那么它会在 bundle 加载的过程中被调用。
initialize方法的调用看起来会更合理,通常在它里面写代码比在 + load 里写更好。+ initialize 很有趣,因为它是懒调用的,也有可能完全不被调用。类第一次被加载时,+ initialize 不会被调用。类接收消息时,运行时会先检查 + initialize 有没有被调用过。如果没有,会在消息被处理前调用。
网友评论