MST

星途 面试题库

面试题:剖析Objective-C中@dynamic属性与运行时机制的深度关联

详细说明@dynamic属性是如何与Objective-C的运行时机制(如消息转发、类对象结构等)相互作用的,举例说明在复杂项目中如何利用这种关联来实现一些高级特性,如动态属性绑定的自定义逻辑。
43.4万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

@dynamic属性与Objective - C运行时机制的相互作用

  1. 与消息转发的关系
    • 在Objective - C中,当调用一个对象的方法(包括访问属性的存取方法)时,如果对象所属的类没有实现该方法,运行时系统会启动消息转发机制。对于使用@dynamic声明的属性,编译器不会自动合成存取方法(gettersetter)。
    • 例如,假设有一个类MyClass声明了一个@dynamic myProperty属性。当代码尝试访问myObject.myProperty时,由于没有自动合成的getter方法,运行时首先会在类的方法列表中查找myPropertygetter方法(通常是- (id)myProperty),找不到后,会进入动态方法解析阶段。如果动态方法解析也未能添加该方法,就会进入备用接收者和完整的消息转发流程。
    • 这意味着开发者可以在消息转发阶段,根据实际需求动态地处理对@dynamic属性的访问,实现自定义的逻辑。
  2. 与类对象结构的关系
    • 类对象在Objective - C运行时中包含了方法列表、属性列表等重要信息。@dynamic属性会影响属性列表的生成。虽然没有自动合成存取方法,但属性依然会被记录在类的属性列表中。
    • 例如,通过运行时函数class_copyPropertyList获取类的属性列表时,@dynamic声明的属性也会包含在内,这使得在运行时可以通过属性名称获取到该属性的相关信息,如属性类型等。这为在运行时动态操作属性提供了基础,即使属性的存取方法不是自动合成的。

在复杂项目中利用这种关联实现高级特性

  1. 动态属性绑定的自定义逻辑
    • 场景:在一个大型的数据库访问框架项目中,希望实现对象属性与数据库字段的动态绑定。不同的数据表结构可能不同,对象的属性需要根据数据库查询结果动态设置。
    • 实现步骤
      • 首先,在数据模型类中使用@dynamic声明属性。例如,有一个UserModel类,声明@dynamic name; @dynamic age;
      • 然后,在运行时,通过消息转发机制来处理属性的存取。在动态方法解析阶段,可以根据数据库查询结果动态地添加存取方法。例如:
#import <objc/runtime.h>

@implementation UserModel

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(name)) {
        class_addMethod(self, sel, (IMP)getterForName, "@@:");
        return YES;
    } else if (sel == @selector(setName:)) {
        class_addMethod(self, sel, (IMP)setterForName, "v@:@");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

id getterForName(id self, SEL _cmd) {
    // 从数据库查询结果中获取name的值并返回
    id nameValue = // 从数据库获取name值的逻辑;
    return nameValue;
}

void setterForName(id self, SEL _cmd, id newName) {
    // 将新的name值更新到数据库
    // 更新数据库name值的逻辑;
}

@end
  • 这样,就实现了属性与数据库字段的动态绑定,根据不同的数据库结构和查询需求,可以灵活地定制属性的存取逻辑,而不需要在编译时就确定固定的属性存取方式。这种方式在复杂的项目中,如具有动态数据结构需求的项目中,能极大地提高代码的灵活性和可维护性。