initialize一般不常用,但是在 SDWebImage 中有使用到它。
initialize
特点:
1.当一个类收到第一条消息时,就会调用这个类的initialize
;
2.可能会调用多次;
3.调用顺序:先调用父类的,再调用子类的;
4.如果分类实现了initialize
,只会调用分类的。
我们从objc4-750源码探究一下initialize
的调用,看看下面例子:
[Man class];
@interface Person : NSObject
@end
@implementation Person
+ (void)initialize {
NSLog(@"person");
}
@end
@interface Man : Person
@end
@implementation Man
+ (void)initialize {
NSLog(@"man");
}
@end
打印结果:person, man
-
initialize
执行依赖于objc_msgSend
,其最相关的是lookUpImpOrForward
,我们就从这个方法开始源码的探索:
IMP lookUpImpOrForward(Class cls, SEL sel, id inst,
bool initialize, bool cache, bool resolver)
{
...
//是否初始化 && 这个类是否被初始化过
if (initialize && !cls->isInitialized()) {
runtimeLock.unlock();
_class_initialize (_class_getNonMetaClass(cls, inst));
runtimeLock.lock();
// If sel == initialize, _class_initialize will send +initialize and
// then the messenger will send +initialize again after this
// procedure finishes. Of course, if this is not being called
// from the messenger then it won't happen. 2778172
}
...
- 然后会递归调用
_class_initialize
,就是在这里决定了,先调用父类再调用子类:
void _class_initialize(Class cls)
{
...
// Make sure super is done initializing BEFORE beginning to initialize cls.
supercls = cls->superclass;//initialize:父亲再到子类
if (supercls && !supercls->isInitialized()) {
_class_initialize(supercls);//递归调用
}
if (reallyInitialize) {
...
#if __OBJC2__
@try
#endif
{
callInitialize(cls);//调用initialize
...
}
}
...
}
- 最终调用
callInitialize
发送消息:
void callInitialize(Class cls)
{
((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);//消息查找流程
asm("");
}
网友评论