MST

星途 面试题库

面试题:Objective-C类别与运行时机制在代码扩展深度优化中的应用

深入理解Objective-C运行时机制,结合类别(Category)特性,说明如何在运行时动态地为类添加属性和方法,以实现更灵活的代码扩展。例如,在不修改原有类的头文件和实现文件的情况下,通过类别和运行时机制为一个已有类添加一个存储特定数据的属性,并实现相关的存取方法。请给出具体的代码实现,并解释其中涉及的运行时原理。
23.3万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

代码实现

假设已有类 Person,我们通过类别为其添加属性 extraData

  1. 导入运行时头文件 在类别实现文件中,导入运行时相关头文件 <objc/runtime.h>
#import <objc/runtime.h>
  1. 定义类别
@interface Person (DynamicProperties)
@property (nonatomic, strong) NSString *extraData;
@end
  1. 实现类别
@implementation Person (DynamicProperties)
static const char kExtraDataKey;
- (void)setExtraData:(NSString *)extraData {
    objc_setAssociatedObject(self, &kExtraDataKey, extraData, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSString *)extraData {
    return objc_getAssociatedObject(self, &kExtraDataKey);
}
@end

运行时原理解释

  1. 关联对象机制
    • 在Objective-C运行时,类别本身并不真正存储属性的实例变量。当我们为类别声明一个属性时,需要通过运行时的关联对象机制来实现属性的存储和访问。
    • objc_setAssociatedObject 函数用于将一个对象(这里是 extraData)与另一个对象(self,即 Person 实例)进行关联,并指定关联策略(OBJC_ASSOCIATION_RETAIN_NONATOMIC 表示强引用且非原子操作)。关联时通过一个唯一的键(这里通过 static const char kExtraDataKey 定义)来标识。
    • objc_getAssociatedObject 函数用于根据指定的键从关联对象中获取对应的对象,从而实现属性的读取。
  2. 方法动态解析 虽然我们在类别中声明和实现了存取方法,但运行时在处理消息发送时,会动态查找和解析方法。当向 Person 实例发送 extraDatasetExtraData: 消息时,运行时会在类别中找到对应的实现并执行。这样就实现了在不修改原有类头文件和实现文件的情况下,为类动态添加属性和方法,达到灵活的代码扩展目的。