2015-06-23 60 views
0
<code> 
//header file has appropriate declarations but not included here: 
#import "AddressCard.h" 

@implementation AddressCard; 

-(NSString *) name 
{ 
    return name; 
} 

//Recommended code: 
-(void) setName: (NSString *) theName 
{ 
    [name release] 
    name = [[NSString alloc] initWthString: theName]; 
} 

//Incorrect code according to Kochan: 
-(void) setName: (NSString *) theName 
{ 
    [name release] 
    name = [NSString stringWthString: theName]; 
} 

//rest of class implementation code snipped 
@end 

<code> 

所以我看到堆棧溢出的代碼不是我的代碼,我不想拿它或任何東西,但我只是有一個關於目標C中的這段代碼的快速問題。 (void) setName: (NSString *) theName方法爲什麼我們必須做[name release]然後​​。爲什麼我們不能簡單地說name = theName。難道那只是將theName變量作爲setName方法中的參數傳遞給原始name變量?複製變量名稱

對不起,如果這是一個不好的問題,但我是新來的目標C和有點困惑來自java背景的內存管理。

+0

此代碼非常舊。內存管理髮生了很大變化,您不再需要包含'release'方法。 –

+0

哦,我不知道這一點。所以在setName方法中,你只需要做name = theName;或者你是否只有name = [[NSString alloc] initWthString:theName];沒有[名稱發佈]代碼?謝謝你的回答。 – Bobby

+0

兩者都是不正確的和古老的。如果'name'和'name'是同一個實例,'name'是唯一保留字符串的指針,'release'在添加之前會將其刪除。需要檢查'theName'!='name'。但這是非ARC內存管理。 – zaph

回答

2

正確的現代風格是在您的項目中使用ARC(自動引用計數),這是新項目的默認值(並且已經過了幾年)。那麼你不需要,也不允許發送release消息。

initWithString:stringWithString:的選擇使得ARC下沒有什麼區別,你還不如把它寫這樣的而不是:

- (void)setName:(NSString *)theName { 
    name = [theName copy]; 
} 

使用copy(或initWithString:stringWithString:),確保您的name即使主叫方通過NSMutableString後再更改內容也不會改變。

但是如果你只是想做你在問題中提出的問題,你可能甚至不需要寫一個setter。所有你需要做的就是把這個在您的.h文件:如果你忽略他們

@interface AddressCard 

@property (nonatomic, strong) NSString *name; 

// other declarations... 

@end 

編譯器會自動生成一個實例變量(命名爲_name),二傳手,併爲你消氣。但是,使用strong意味着編譯器生成的setter不會複製該字符串;它只會保持對調用者給出的字符串的引用。

如果你想如我上述使用copy,財產申報是這樣,而不是:

@property (nonatomic, copy) NSString *name; 

編譯器會生成使用copy二傳手。

+0

哇,這是我見過的最混亂的語言......儘管我非常感謝你的回答。謝謝你做了很多。 – Bobby

+0

另外你提到編譯器會自動生成一個setter方法,它使用下面這行代碼進行復制:@property(nonatomic,copy)NSString * name。我如何使用這個自動生成的setter方法,因爲我不知道編譯器創建的這個方法的名字? – Bobby

+1

setter方法將被命名爲'setName:'。 –