美文网首页
系统底层源码分析(3)——initialize

系统底层源码分析(3)——initialize

作者: 无悔zero | 来源:发表于2021-01-04 21:10 被阅读0次

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

  1. 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
    }
    ...
  1. 然后会递归调用_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
            ...
            }
        }
        ...
    }
  1. 最终调用callInitialize发送消息:
void callInitialize(Class cls)
{
    ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);//消息查找流程
    asm("");
}

相关文章

网友评论

      本文标题:系统底层源码分析(3)——initialize

      本文链接:https://www.haomeiwen.com/subject/ootloktx.html