MST

星途 面试题库

面试题:Objective-C中@property声明属性时@dynamic的作用及应用场景

在Objective-C的@property声明属性时,@dynamic关键字有什么作用?请举例说明在哪些实际场景下会用到@dynamic,并且说明使用@dynamic后与默认情况在实现机制上有什么不同。
21.4万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

@dynamic关键字的作用

在Objective-C中,@dynamic关键字用于告诉编译器,属性的存取方法(getter和setter)将在运行时动态提供,而不是由编译器自动生成。这意味着编译器不会为该属性合成(synthesize)实例变量和存取方法。

实际场景

  1. 延迟实现存取方法
    • 例如,在Core Data框架中,实体类的属性经常使用@dynamic声明。Core Data实体类的属性值存储在持久化存储中,其存取方法是在运行时根据数据模型和存储状态动态生成的。
    // 假设我们有一个Core Data实体类Person
    @interface Person : NSManagedObject
    @property (nonatomic, strong) NSString *name;
    @end
    
    @implementation Person
    @dynamic name;
    @end
    
    • 这里name属性使用@dynamic,因为Core Data在运行时会根据数据库中Person实体的实际存储情况,动态生成name属性的存取方法。
  2. 自定义存取逻辑
    • 当你想完全自定义属性的存取逻辑,并且不希望编译器合成默认的存取方法时,可以使用@dynamic。比如,属性值是通过复杂的计算或网络请求获取的,而不是简单的实例变量存储。
    @interface MyClass : NSObject
    @property (nonatomic, assign) int customProperty;
    @end
    
    @implementation MyClass
    @dynamic customProperty;
    - (int)customProperty {
        // 这里可以实现复杂的计算逻辑,比如从其他属性计算得出
        return self.otherProperty1 + self.otherProperty2;
    }
    - (void)setCustomProperty:(int)value {
        // 这里可以实现自定义的设置逻辑,比如更新相关的其他属性
        self.relatedProperty = value * 2;
    }
    @end
    

实现机制的不同

  • 默认情况(使用@synthesize或不写时)
    • 编译器会自动为属性合成实例变量和存取方法。例如,对于@property (nonatomic, strong) NSString *name;,编译器会生成一个名为_name的实例变量(默认命名规则),以及name的getter方法- (NSString *)name和setter方法- (void)setName:(NSString *)newName。这些方法会直接操作实例变量_name
  • 使用@dynamic
    • 编译器不会合成实例变量和存取方法。你需要在运行时自己提供这些方法,或者由运行时环境(如Core Data)动态生成。如果在运行时没有找到对应的存取方法,会导致运行时错误(通常是unrecognized selector sent to instance错误)。所以使用@dynamic要求开发者对属性的存取有更精确的控制和实现。