属性是一种定义类所提供的数据的通常方法。在Movie这个类里,诸如“标题”,“工作室”和“发布年份”等等都算是属性。这里是用Objective-C 1.x语法定义的Movie类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @interface Movie : NSObject { NSString* title; NSString* studio; int yearReleased; } + (id)movie; - (NSString*)title; - (void)setTitle:(NSString*)aValue; - (NSString*)studio; - (void)setStudio:(NSString*)aValue; - (int)yearReleased; - (void)setYearReleased:(int)aValue; - (NSString*)summary; @end |
这里是它在Objective-C 2.0里面的样子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @interface Movie : NSObject { NSString* title; NSString* studio; NSInteger yearReleased; } + (id)movie; @property (copy) NSString* title; @property (copy) NSString* studio; @property (assign) NSInteger yearReleased; @property (readonly) NSString* summary; @end |
需要注意的是并不是所有的东西都是属性。假如有一个生成新object的类方法 +move,这一类的东西不需要被声明成属性。
属性的定义格式如下:
1 | @property (<parameters>) <type> <name>; |
assign关键字代表setter直接赋值,而不是复制或者保留它。这种机制非常适合一些基本类型,比如NSInteger和CGFloat,或者你并不直接拥有的类型,比如delegates。
readonly关键字代表setter不会被生成, 所以它不可以和 copy/retain/assign组合使用。我们把 summary 定义为 readonly 是因为它并不需要一个专门的类变量,相应的,我们会在用到的时候动态生成它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | @implementation Movie + (id)movie { return [[[Movie alloc] init] autorelease]; } - (NSString*)title { return title; } - (void)setTitle:(NSString*)aValue { [title autorelease]; title = [aValue copy]; } - (NSString*)studio { return studio; } - (void)setStudio:(NSString*)aValue { [studio autorelease]; studio = [aValue copy]; } - (int)yearReleased { return yearReleased; } - (void)setYearReleased:(int)aValue { yearReleased = aValue; } - (NSString*)summary { NSNumber* yearAsObject; yearAsObject = [NSNumber numberWithInt:[self yearReleased]]; return [NSString stringWithFormat:@"%@ by %@, released in %@", [self title], [self studio], yearAsObject]; } @end |
这里是 Objective-C 2.0 版本(启用了垃圾回收):
@synthesize 指令生成了相应的访问方法,垃圾回收代表 +movie 不需要 autorelease它返回的object。还有,我们使用了self.title,self.studio替代了[self title]和[self studio]。
现在让我们从使用者的角度看看Movie类:
1 2 3 4 5 6 | Movie* newMovie = [Movie movie]; newMovie.title = @"The Incredibles"; newMovie.studio = @"Pixar"; newMovie.yearReleased = 2004; NSLog (@"Movie summary: %@", newMovie.summary); |
运行结果:
1 | Movie summary: The Incredibles, by Pixar. Released in 2004. |
在Objective-C 2.0中你可以同时使用两种属性访问方式。”.”操作符并不是唯一的方法。你也可以使用”.”访问没有被明确定义的属性。例如:
1 2 | NSString* newString = [textField stringValue]; NSString* newString = textField.stringValue; |
@property和@synthesize的区别可能在一开始并不容易看出来。@property定义一个已经存在的属性,而@synthesize实现了具体的访问方法,如果需要的话。
注:当getter需要返回一个有效值的时候synthesize标记会被默认使用。如果启用了垃圾回收的话,这不会产生任何额外的开销。你可以使用 nonatomic 关键字来禁用这个行为。