底层5:Category、+load、+initialize

2020-08-29  本文已影响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调用。

上一篇下一篇

猜你喜欢

热点阅读