虽然对这个已经很熟了,但是还是看了一遍,生怕遗漏了什么
转载自:http://blog.csdn.net/kmyhy/article/details/8571739
原文:http://iphonedevsdk.com/forum/iphone-sdk-tutorials/7295-getters-setters-and-properties-for-the-newbie.html
对于有Mac开发经验的iPhone开发者,可能对O-C的注解“@property”已经习以为常了。但对于从其他开发平台(Java或者Symbian)迁移过来的iPhone开发者,“@property”仍然有点麻烦。为了使这些人不再犯我一样的错误,本文简单探讨了变量及属性,以及它们所采用的内存管理。
首先来看一个简单类:
//MyClass.h file
@interface MyClass: NSObject
{
NSString *text;
}
-(void) init;
-(void) logText;
@end
//MyClass.m file
@implementation MyClass
- (void)init
{
text = @\"sometext\";
}
- (void)logText
{
NSLog(@\"%@\", text);
}
@end
这个类十分简单。它唯一的成员就是text,一个NSString。text变量在init方法中初始化,在logText方法中被引用。
就目前而言,text变量中存储的是常量值,我们无须关心它的内存管理。但在真正的程序中,我们可能会想在运行时改变text的值,因此需要为它设计getter和setter方法:
//MyClass.h file
@interface MyClass: NSObject
{
NSString *text;
}
-(void) init;
-(void) logText;
-(NSString*) text;
-(void) setText:(NSString *)textValue;
@end
//MyClass.m file
@implementation MyClass
- (void)init
{
text = @\"sometext\";
}
- (void)logText
{
NSLog(@\"%@\", text);
}
-(NSString*) text
{
return text;
}
-(void) setText:(NSString *)textValue
{
if (textValue !=text)
{
[textValue retain];
[text release];
text = textValue;
}
}
-(void)dealloc
{
[text release];
[super dealloc];
}
@end
接下来,我们需要:
一、添加一个方法,读取当前的text属性:
NSString *theTextValue = [obj text];
(假设 "obj" 是一个MyClass实例)
这个方法很简单 - 仅仅是返回text属性值。
二、在另一个方法中,改变text属性:
[obj setText:newStringValue];
(假设 "obj" 是一个MyClass实例, "newStringValue" 是一个 NSString).
在setText:方法中,由于我们无法确定newStringValue到底是不是一个常量——它可能是任何NSString值,包括在堆中分配的NSString。因此,我们要“retain”这个(将要赋值给text的)对象,以确保这个对象能够和MyClass对象的生命周期一样长。同样,对于已经被替换掉的旧有值,我们不应当再持有它,因此我们释放了它。if语句的使用,是为了减少不必要的赋值——当然,你也可以不用它:
-(void) setText:(NSString *)textValue
{
[textValue retain];
[text release];
text = textValue;
}
即使textValue和text值相同,代码也会被执行,因为我们先在引用计数器上+1,然后再减1。注意,这种写法是错误的:
-(void) setText:(NSString *)textValue
{
[text release];
[textValue retain];
text = textValue;
}
这是因为,当“输入”值和要“持有”的值指向了同一个NSString的情况下,会导致字符串最终将被deallocated——第1句代码有可能将引用计数减为0,导致对象被仍会堆里。第2句代码试图去retain这个已经释放的对象(由于二者是同一个)。这种情况不一定发生,但却是一个隐患。
最后,我们实现dealloc方法,在其中释放text对象。我们既然retain了某些东西,就需要记得release它,就好比人临死的时候,要记得把借的书还给图书馆。
值得注意的是,进行空赋值这些代码仍然工作得很好。O-C有个奇怪的特点,允许向nil发送消息(比如release和retain消息)而不会出任何错误。类似于++ 中可以释放一个null指针。
现在,更有趣的事情来了。我们将加入第2个成员变量,以及它的getter和setter。很快你就会看到将发生什么。
//MyClass.h file
@interface MyClass: NSObject
{
NSString *text;
int value;
}
-(void) init;
-(void) logText;
-(NSString*) text;
-(void) setText:(NSString *)textValue;
-(int) value;
-(void) setValue:(int*)intValue;
@end
//MyClass.m file
@implementation MyClass
- (void)init
{
text = @\"sometext\";
value = 2;
}
- (void)logText
{
NSLog(@\"%@\", text);
}
-(NSString *) text
{
return text;
}
-(void) setText:(NSString *)textValue
{
if (textValue !=text)
{
[textValue retain];
[text release];
text = textValue;
}
}
-(int) value
{
return value;
}
-(void) setValue:(int)intValue
{
value = intValue;
}
-(void)dealloc
{
[text release];
[super dealloc];
}
@end
这次,我们简单地加入了一个整型变量以及setter/getter方法。但这次,我们不需要retain 和release 。因为整型不是在堆中分配的-它直接存储在MyClass中。我们可以这样干:
NSString *s = [objtext];
[objsetText:@\"new string\"];
int i = [obj value];
[obj setValue:3];
现在,类似的getter/setter方法在O-C中实在是多得让人写不胜写。因此O-C也提供了更简单的方式为我们自动生成这些方法。我们可以将上述代码修改为:
//MyClass.h file
@interface MyClass: NSObject
{
NSString *text;
int value;
}
@property(nonatomic, retain) NSString *text;
@property(nonatomic, assign) int value;
-(void) init;
-(void) logText;
@end
//MyClass.m file
@implementation MyClass
@synthesize text;
@synthesize value;
- (void)init
{
text = @\"sometext\";
value = 2;
}
- (void)logText
{
NSLog(@\"%@\",text);
}
-(void)dealloc
{
[text release];
[super dealloc];
}
@end
首先,在MyClass.h中我们移除了两个getter方法和两个setter方法。代之以两个"@property"开头的语句。
在 MyClass.m中,我们删除了所有的setter/getter方法,代之以两个"@synthesize"开头的语句。
这和前面的代码是一模一样的。 回想一下,写一个getter也是很简单的:你只需要知道将返回哪个变量以及变量的类型就行了,这样就很容易写出代码了。对于setter,你需要知道的是:正在对哪个变量赋值,以及它的类型,以及是否是简单赋值(例如int类型的属性)或者是否需要进行retain/release(例如NSString属性)。
然而,现在我们只需要4个"@"语句就行了:
@property(nonatomic, retain)NSString *text;
翻译过来就是“我有一个NSString类型的成员变量 'text'。我需要一对getter/setter方法(使用retain/release)”。
@property(nonatomic, assign) intvalue;
翻译过来就是“我有一个int型成员变量 'value'。我需要一对使用简单赋值而不是retain/release的getter/setter方法”。
@synthesize text;
翻译过来就是“请为 'text'自动生成getter/setter方法代码”。
@synthesize value;
翻译过来就是“请为 'value'自动生成getter/setter方法代码”。
注意,我们仍然需要在dealloc方法中release对象。O-C显然还无法自动帮我们做这些事情。