OC中的Category(三)

2018-11-20  本文已影响4人  aaayia

OC中的Category(三)

OC中+initialize函数加载和调用

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

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

+initialize和+load的区别

  1. 调用方式
  1. 调用时刻

load、initialize的调用顺序?

  1. load
  1. 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("");
}


上一篇下一篇

猜你喜欢

热点阅读