iOS

load 和 initialize方法

Posted by shefh on October 1, 2016

在 NSObject 类中有两个非常特殊的类方法 +load 和 +initialize ,用于类的初始化.下面介绍下他们的调用时机和一些使用的场景。

Demo

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSLog(@" main func run");
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

//父类
@implementation TestViewController
+(void)load {
    NSLog(@" TestViewController run load");
}
+(void) initialize {
    NSLog(@"TestViewController run initialize ");
}
@end

//子类
@interface ChildViewController : TestViewController
@end
@implementation ChildViewController
+(void)load {
    NSLog(@" ChildViewController run load");
}
+(void) initialize {
    NSLog(@"ChildViewController run initialize ");
}
@end

+load

Demo加载顺序

  TestViewController run load
  ChildViewController run load
  main func run

+load 加载时机

  • 类的加载,调用时机是是类被加入的runtime的时候。测试发现,它在程序main函数之前执行之前加载。
  • 父类的+load 会在之类加载之前加载。每个分类的+load加载是没有书序的。
  • 只要工程里面有类,这个类不需要被包含或者使用+load方法都会被执行。

    使用场景

  • +load方法是线程安全的,它内部使用了锁.所以需要避免一些带锁额操作。
  • 一般在这里实现一些类的方法替换。

+initialize

加载顺序

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
     [TestViewController new];    
    return YES;
}
// 结果为
  TestViewController run load
  ChildViewController run load
  main func run
  TestViewController run initialize 

/*************************/
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {         
    [ChildViewController new];
    return YES;
}
// 结果为
  TestViewController run load
  ChildViewController run load
  main func run
  TestViewController run initialize
  ChildViewController run initialize 

+initialize 加载时机

  • 在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。
  • 如果一个子类没有实现 +initialize 方法,那么父类的实现是会被执行多次的。如果有多个类继承自同一个类,如果子类都实现了+initialize方法,那么父类的+initialize方法只会被执行一次。如果子类没有实现+initialize方法,这个时候会调用父类的+initialize方法,这导致了父类的+initialize方法被执行多次。
  • 为了确保初始化方法在+initialize被执行一次,可以使用如下方法:
 + (void)initialize {
  if (self == [ClassName self]) {
    // ... do the initialization ...
  }
}
@interface Child2ViewController : TestViewController
@end

@implementation Child2ViewController
+(void)load {
    NSLog(@" Child2ViewController run load");
}
//+(void) initialize {
//    NSLog(@"Child2ViewController run initialize ");
//}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
@end

  [ChildViewController new];
  [Child2ViewController new];

//执行结果为
  TestViewController run load
  Child2ViewController run load
  ChildViewController run load
  main func run
  TestViewController run initialize 
  ChildViewController run initialize 
  TestViewController run initialize 

使用场景

  • 可以把一些需要懒加载的的初始化的方法存放到这边。

参考资料

Objective-C +load vs +initialize