雖然對這個已經很熟了,但是還是看了一遍,生怕遺漏了什麼
轉載自: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顯然還無法自動幫我們做這些事情。