美文网首页
底层5:Category、+load、+initialize

底层5:Category、+load、+initialize

作者: 张无奈 | 来源:发表于2020-08-29 14:26 被阅读0次

    面试题:Category

    1.Category的使用场合时什么?

    2.Category的实现原理。

    Category编译后的底层结构是struct Category_t,里面存储分类的对象方法、类方法、属性、协议信息。在程序运行的时候,runtime会将Category的数据,合并到类信息中(类对象、元类对象中)

    3.Category的Class Extension的区别是什么?

    Class Extension在编译的时候,它的数据就已经包含在类信息中。Category是在运行时,才会将数据合并到类信息中。

    4.Category中有load方法吗?load方法什么时候调用的?load方法能继承吗?

    有+load方法;

    load方法在runtime加载类、分类的时候调用;

    load方法严格来说可以继承,但是一般情况下不回去主动调用,都是让系统自动去调用。

    5.load、initialize方法的区别是什么?他们在category中的调用顺序?以及出现继承时他们之间的调用过程?

    区别:

    调用方式:

    1)load是根据函数地址直接调用;

    2)initialize是通过objc_msgSend调用。

    调用时刻:

    1)load是runtime加载类、分类的时候调用(只会调用一次);

    2)initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)。

    调用顺序:

    1.load调用顺序:

    1>先调用类的load。

    a)先编译的类,优先调用load;

    b)调用子类的load之前,会先调用父类的load。

    2>再调用分类的load。

    a)先编译的分类,优先调用load。

    2.initialize调用顺序:

    1> 先初始化父类

    2> 再初始化子类(可能最终调用的是父类的+initialize)

    继承调用顺序:

    调用子类的load之前,会先调用父类的load。

    先调用父类的initialize,再调用子类的initialize(如果子类没有initialize,会调用父类的initialize)。


    Category的原理:

    通过Runtime加载某个类的所有Category数据。

    把所有Category的方法、属性、协议数据,合并到一个大的数组中,后面参与编译的Category数据,会在数据的前面。

    将合并后的分类数据(方法、属性、协议)插入到类原来数据的前面。

    Category的底层结构

    +load方法

    +load方法会在runtime加载类、分类时调用。

    每个类、分类的+load方法在程序运行过程中只调用一次

    调用顺序:

    1.先调用类的+load方法。

    按照编译先后顺序调用(先编译,先调用);

    调用子类的+load方法之前会先调用父类的+load方法。

    2.再调用分类的+load方法。

    按照编译先后顺序(先编译,先调用)。

    +initialize方法:会在类第一次接收到消息的时候调用。

     是通过消息机制来调用的。

    调用顺序:

    先调用父类的+initialize,再调用子类的+initialize(可能不会调用)。

    (先初始化父类,在初始化子类,每个类只初始化一次。)

    +initialize和+load最大的区别是:

    +initialize是通过objc_msgSend进行调用的,所以有以下特点:

    1)如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次);

    2)如果分类实现了+initialize,就会覆盖本身的+initialize调用。

    相关文章

      网友评论

          本文标题:底层5:Category、+load、+initialize

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