美文网首页
Category与+load、+initialize方法

Category与+load、+initialize方法

作者: 丶月月鸟 | 来源:发表于2020-01-03 11:31 被阅读0次

    Catergory

    在编译时,会将分类生成一个category_t结构体

    category_t结构体

    分类的本质:runtime会将分类中的方法、协议、属性分别拼接成3个数组,且分类方法、协议、属性的顺序和分类的编译顺序有关,后编译的会在前面。然后回将生成的数组进行momerymove(内存移动)操作,拼接在类对象和元类对象的rw->method_list等属性的最前面

    分类源码调用顺序:

    在pobjc-os.mm文件中

    _objc_init 

    map_images

    map_images_nolock

    在pobjc-runtime-new.mm 文件中

    _read_images

    remethodizeClass

    attachCategories

    attachLists

    realloc、memmove、 memcpy


    +load方法

    调用时机:会在runtime加载类和分类时调用,且只调用一次。

    调用顺序:分类的+ load方法和类的 + load方法都会调用,且一定是原类中的load方法先调用,因为在源码中,会先找到原类中的+ load方法的内存地址,直接单独调用,再按照分类文件的编译顺序进行分别调用分类中的+ load方法,先编译的先调用。

    源码调用顺序: 

    +load方法调用过程

    +initialize方法

    调用时机:+initialize方法,是在类第一次调用objc_msgSend方法前调用,即类第一次接收到消息前调用

    调用顺序:+initialize方法在源码中,先判断当前类是否调用过+initialize(initialized);如果没有调用过,则会通过递归的方法寻找其父类的+initialize方法;接下来会判断当前父类是否initialized,如果父类没有调用过则父类先调用callInitialize即调用+initialize方法,再进行调用子类的+initialize方法。

    源码调用顺序:

    在pobjc-msg-arm64.s文件中

    objc_msgSend

    在pobjc-runtime-new.mm文件中

    class_getInstanceMethod

    lookUpImpOrNil

    lookUpImpOrForward

    _class_initialize

    callInitialize

    objc_msgSend(cls, SEL_initialize)

    区别:

    1)+initialize方法是通过objc_msgSend方法调用,与load方法的直接通过地址指针进行调用不同

    2)如果子类没有调用+initialize方法,且子类不存在+initialize方法,则会调用父类的+initialize方法,因此父类的+initialize方法有可能会调用多次

    3)因为+initialize方法是通过objc_msgSend方法调用,因此分类的+initialize方法会覆盖本身的+initialize方法

    相关文章

      网友评论

          本文标题:Category与+load、+initialize方法

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