OC中的Category(三)

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(三))