面试题答案
一键面试1. 类的category在类结构中的存储形式
- Category的数据结构:Category在Objective-C运行时用
category_t
结构体来表示。它包含了一些关键信息,例如指向类的指针Class cls
,category的名称const char *name
,方法列表method_list_t *instanceMethods
,类方法列表method_list_t *classMethods
,协议列表protocol_list_t *protocols
等。 - 存储位置:Category并没有像类的属性、方法等直接存储在类对象内部。它有自己独立的结构体,在运行时通过runtime机制与类关联起来。
2. 加载过程
- 编译期:编译器会为每个category生成一个
category_t
结构体,包含了category中定义的方法、属性、协议等信息。 - 运行期:
- dyld动态链接:当程序启动时,dyld动态链接器加载相关的动态库。
- runtime加载:runtime开始处理类和category的加载。runtime会遍历所有的category,将它们的信息合并到对应的类中。具体来说,runtime会将category的方法列表、协议列表等添加到类的相应列表中。在加载category时,runtime会先处理类的主实现,然后再处理相关的category。
3. 对类的方法列表的影响
- 方法添加:category中的实例方法会被添加到类的实例方法列表中,类方法会被添加到类的类方法列表中。
- 方法覆盖(Method Swizzling):如果category中定义的方法与类本身或其他category中的方法同名,在运行时,后加载的category的方法会覆盖先加载的同名方法。这是因为runtime在合并方法列表时,后处理的category的方法会被放在方法列表的前面,在消息发送时,runtime会优先找到前面的方法并调用。需要注意的是,这种覆盖并不是真正意义上的替换原有方法的实现,而是在方法查找顺序上的调整。