面试题答案
一键面试@dynamic关键字的作用
在Objective-C中,@dynamic
关键字用于告诉编译器,属性的存取方法(getter和setter)将在运行时动态提供,而不是由编译器自动生成。这意味着编译器不会为该属性合成(synthesize)实例变量和存取方法。
实际场景
- 延迟实现存取方法:
- 例如,在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
属性的存取方法。
- 例如,在Core Data框架中,实体类的属性经常使用
- 自定义存取逻辑:
- 当你想完全自定义属性的存取逻辑,并且不希望编译器合成默认的存取方法时,可以使用
@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
要求开发者对属性的存取有更精确的控制和实现。
- 编译器不会合成实例变量和存取方法。你需要在运行时自己提供这些方法,或者由运行时环境(如Core Data)动态生成。如果在运行时没有找到对应的存取方法,会导致运行时错误(通常是