美文网首页
系统底层源码分析(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