--存在类别关系时initialize和load的调用问题--
1,类别不会调用类的load方法
示例代码一
@interface SuperClass : NSObjec
@end
@implementation SuperClass
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface SuperClass (OneClass)
@end
@implementation ChildClass
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface SuperClass (TowClass)
@end
@implementation SuperClass (TowClass)
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
示例代码一中
OneClass和TowClass都是SuperClass的类别,并且都重写了SuperClass的load方法。
现在我们在Xcode的项目中只简单的import这几个类,而不去使用它们。然后运行项目,获得下面的结果:
//示例代码一
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
此时:如果我们删除掉OneClass类别中重写的load方法,重新运行项目,获得下面的结果:
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
根据打印结果,可以看出:
如果OneClass没有重写load方法,则其不会执行SuperClass的load方法。所以,类别中的load和继承中的load是一样的,只不过Category的load会在主类的load调用之后才会执行。
2,类别会覆盖类的initialize方法
示例代码二
@interface SuperClass : NSObject
@end
@implementation SuperClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface SuperClass (OneClass)
@end
@implementation SuperClass (OneClass)
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface SuperClass (TowClass)
@end
@implementation SuperClass (TowClass)
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
示例代码二中:
两个类别OneClass和TowClass都重写了load方法和initialize方法。这里重写load是为了触发initialize方法。
现在我们在Xcode的项目中只简单的import这几个类,而不去使用它们。然后运行项目,获得下面的结果:
//示例代码二
SuperClass +[SuperClass(OneClass) initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
此时我们注释掉OneClass重写的initialize方法,再次运行程序,获得下面的结果:
//示例代码二
SuperClass +[SuperClass(TowClass) initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
接着我们注释掉TowClass重写的initialize方法,再次运行程序,获得下面的结果:
//示例代码二
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
最后我们注释掉SuperClass的initialize方法,再次运行程序,获得下面的结果:
//示例代码二
+[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
OK,有没有发现什么规律?先别着急说,接着往下看。
现在,我们放开TowClass的注释,再次运行程序,获得下面的结果:
//示例代码二
SuperClass +[SuperClass(TowClass) initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
然后我们放开OneClass的注释,再次运行程序,获得下面的结果:
//示例代码二
SuperClass +[SuperClass(OneClass) initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
最后我们放开SuperClass的注释,再次运行程序,获得下面的结果:
//示例代码二
SuperClass +[SuperClass(OneClass) initialize]
SuperClass +[SuperClass load]
SuperClass +[SuperClass(TowClass) load]
SuperClass +[SuperClass(OneClass) load]
好了,现在你可以大胆的猜测,在分类中,initialize的调用顺序是什么了。
总结:
1,initialize的调用肯定与load的调用顺序有关。
2,类别中如果没有重写initialize,则不会调用类中的initialize。
3,各个类别中重写initialize,互相没有影响。一个类别中没有重写不会调用其他类别中已经重写的initialize。
4,如果类和类别中重写了initialize方法,运行程序时,只会有一个重写的方法被运行时提前并自动运行。
====>那么到底会运行哪一个重写的initialize呢?<====
@1,通过重写类和每个类别的load方法,确定它们被引用的顺序。
@2,确定类和类别中重写了initialize方法的。
@3,根据引用顺序找出最后一个重写了initialize的类别,则该类别重写的initialize会被运行时自动运行,其他重写的initialize不会被自动运行。
资料链接:
[IDER]:
http://blog.iderzheng.com
http://blog.iderzheng.com/objective-c-load-vs-initialize/
[MrPeak杂货铺]:http://blog.csdn.net/hanangellove/article/details/45033453
[知乎上的一个怎么面试iOS工程师的问题]:
http://blog.csdn.net/hanangellove/article/details/45033453