美文网首页
OC中的Category(三)

OC中的Category(三)

作者: aaayia | 来源:发表于2018-11-20 20:37 被阅读4次

    OC中的Category(三)

    OC中+initialize函数加载和调用

    OC对象是在查找方法时判断自己有没有初始化,如果没有就会调用初始化方法,在调用自己的初始化方法之前会调用父类的初始化方法。

    调用initialize方法是通过runtime的objc_msgSend的方式调用,所以会存在如果子类没有实现会调用父类的initialize方法,并且优先调用类分类中存在的initializ方法

    • +initialize方法会在类第一次接收到消息时调用
    • 调用顺序:
      先调用父类的+initialize,再调用子类的+initialize
      (先初始化父类,再初始化子类,每个类只会初始化1次)

    +initialize和+load的区别

    1. 调用方式
    • load是根据函数地址直接调用
    • initialize是通过objc_msgSend调用,如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)如果分类实现了+initialize,就覆盖类本身的+initialize调用
    1. 调用时刻
    • load是runtime加载类、分类的时候调用(只会调用1次)
    • initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)

    load、initialize的调用顺序?

    1. load
    • 先调用类的load,先编译的类,优先调用load,调用子类的load之前,会先调用父类的load

    • 再调用分类的load,
      先编译的分类,优先调用load

    1. initialize
    • 先初始化父类
    • 再初始化子类(可能最终调用的是父类的initialize方法)

    源码分析

    objc-run-timenew.mm文件,查找方法实现

    runtime中initialize方法的调用
    Method class_getInstanceMethod(Class cls, SEL sel)
    {
        if (!cls  ||  !sel) return nil;
    
        // This deliberately avoids +initialize because it historically did so.
    
        // This implementation is a bit weird because it's the only place that 
        // wants a Method instead of an IMP.
    
    #warning fixme build and search caches
            
        // Search method lists, try method resolver, etc.
        lookUpImpOrNil(cls, sel, nil, 
                       NO/*initialize*/, NO/*cache*/, YES/*resolver*/);
    
    #warning fixme build and search caches
    
        return _class_getMethod(cls, sel);
    }
    
    
    IMP lookUpImpOrNil(Class cls, SEL sel, id inst, 
                       bool initialize, bool cache, bool resolver)
    {
        IMP imp = lookUpImpOrForward(cls, sel, inst, initialize, cache, resolver);
        if (imp == _objc_msgForward_impcache) return nil;
        else return imp;
    }
    
    
    IMP lookUpImpOrForward(Class cls, SEL sel, id inst, 
                           bool initialize, bool cache, bool resolver)
    {
        .
        .
        .
        if (initialize  &&  !cls->isInitialized()) {
            runtimeLock.unlockRead();
            _class_initialize (_class_getNonMetaClass(cls, inst));
            runtimeLock.read();
        }
        .
        .
        .
        
    }
    
    void _class_initialize(Class cls)
    {
        assert(!cls->isMetaClass());
        Class supercls;
        bool reallyInitialize = NO;
        supercls = cls->superclass;
        if (supercls  &&  !supercls->isInitialized()) {
            _class_initialize(supercls);
        }
        
        callInitialize(cls);
    
    
    }
    
    void callInitialize(Class cls)
    {
        ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);
        asm("");
    }
    
    
    

    相关文章

      网友评论

          本文标题:OC中的Category(三)

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