objective-c 2.0中增加了一个新的关键字@dynamic, 用于定义动态属性。所谓动态属性相对于@synthesis,不是由编译器自动生成setter或者getter,也不是由开发者自己写的setter或getter,而是在运行时动态添加的setter和getter。
一般我们定义一个属性都是类似以下方法:
@interface Car:NSObject; @property (retain) NSString* name; @end @implement Car; @synthesize name; @end
这种情况下,@synthesize关键字告诉编译器自动实现setter和getter。另外,如果不使用@synthesize,也可以自己实现getter或者setter
@implement Car; (NSString*) name{ return _name; } (void) setName:(NSString*) n{ _name = n; }
现在通过@dynamic,还可以通过第三种方法来实现name的setter和getter。实现动态属性,需要在代码中覆盖resolveInstanceMethod来动态的添加name的setter和getter。这个方法在每次找不到方法实现的时候都会被调用。事实上,NSObject的默认实现就是抛出异常。
参考以下代码:
下面是定义动态属性和实现动态属性的代码:
@interface Car:NSObject @property (retain) NSString* name; @end ---car.m (void) dynamicSetName(id SELF, SEL _cmd, NSString * n){ //这个定义形式是必须的。 //结合下面的类型描述字符v表示返回为void //@表示第一个参数id //:表示SEL //@表示参数n NSLog(@"the new name is going to send in:%@!", n); } @implement Car @dynamic name; -(BOOL) resolveInstanceMethod:(SEL) sel{ NSString * method = NSStringFromSelector(sel); if([method isEqualToString:@"setName:"]){ class_addMethod([self class], sel, (IMP)dynamicSetName, "v@:@");//类型描述字符,可以参考开发文档中有关@encode关键字的说明。 return YES: } return [super resolveInstanceMethod:sel]; } @end;
上面的代码动态实现了name的setter,当然这个时候如果想要调用car.name,就会抛出错误,因为我并没有实现它的getter。