Objective-C 有兩個神奇的方法:+load 和 +initialize,這兩個方法在類被使用時會自動調用。但是兩個方法的不同點會導致應用層面上性能的顯著差異。
1.+ initialize 方法和+load 調用時機
1.1 + initialize 方法:
會在第一次初始化這個類之前被調用,我們用它來初始化靜態(tài)變量。
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 方法會被默認執(zhí)行,并且是在 main 函數之前執(zhí)行的。
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 方法類似一個懶加載,如果沒有使用這個類,那么系統(tǒng)默認不會去調用這個方法,且默認只加載一次;
- initialize 的調用發(fā)生在 +init 方法之前。
3.總結
如果你實現了 + load 方法,那么當類被加載時它會自動被調用。這個調用非常早。如果你實現了一個應用或框架的 + load,并且你的應用鏈接到這個框架上了,那么 + load 會在 main() 函數之前被調用。如果你在一個可加載的 bundle 中實現了 + load,那么它會在 bundle 加載的過程中被調用。
initialize方法的調用看起來會更合理,通常在它里面寫代碼比在 + load 里寫更好。+ initialize 很有趣,因為它是懶調用的,也有可能完全不被調用。類第一次被加載時,+ initialize 不會被調用。類接收消息時,運行時會先檢查 + initialize 有沒有被調用過。如果沒有,會在消息被處理前調用。