深入理解iOS中load方法和initialize方
深入理解iOS中load方法和initialize方法
在ios面试的时候,面试官经常会问load方法和initalize方法有什么区别和共同点。接下来我们就理解一下这两个方法。
首先来看看苹果官方文档对这两个方法的说明:
initialize: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.
load:Invoked whenever a class or category is added to the Objective-C ,runtime; implement this method to perform class-specific behavior upon loading.
表面意思就是说:initialize方法是在第一次调用该类的方法的时候调用,load方法是在程序启动之前就调用,父类先于子类执行,类先于分类执行。
@interface ParentClass : NSObject
@end
@interface ChildClass : NSObject
@end
@interface OtherClass : NSObject
-(void)completeMethod;
@end
@implementation ParentClass
+(void) initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+(void) load{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
@end
@implementation ChildClass
+(void) initialize{
NSLog(@"%@ %s",[self class],__FUNCTION__);
OtherClass *other = [[OtherClass alloc] init];
[other completeMethod];
}
@end
@implementation OtherClass
-(void)completeMethod{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+(void) load{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+(void) initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
@end
说明:一个ParentClass类实现了+(void)load和+(void)initialize方法,ChildClass继承于ParentClass只重写了initialize方法,OtherClass类重写了+(void)load和+(void)initialize方法,ChildClass的initialize方法中构建了一个OtherClass类对象,在方法的实现中只打印了当前的类名和方法名。
我们首先在工程中只是引入这些类,而不去使用他们,运行之后的结果:
ParentClass +[ParentClass initialize]
ParentClass +[ParentClass load]
OtherClass +[OtherClass initialize]
OtherClass +[OtherClass load]
就像Apple文档所说的那样,只要有引用runtime就会去调用类的+(void)load方法,从输出可以看出ParentClass的+(void)initialize方法也调用了,而且是在initialize方法之前,那是因为在+(void)load方法中调用了[self class]方法,这个方法触发了initialize方法的执行。load和initialize方法都不需要手动的去调用super方法,父类的执行顺序在子类之前。当在程序中把所有的[self class]删除之后,initialize方法都不会调用。
总结:
1.load和initialize都会在实例化对象之前调用,以main函数为分水岭,前者是在main函数之前,后者是在main函数之后。
2.load和initialize方法都不会显示的调用父类的方法而是自动调用,即使子类没有initialize方法也会调用父类的方法,load方法不会调用父类。
3.load和initialize方法内部使用了锁,因此他们是线程安全的,实现时要尽可能简单,避免线程阻塞,不要再次使用锁。
4.load方法常用来method swizzle,initialize常常用于初始化全局变量和静态变量.