2012-08-25 35 views
2

在以下示例中,不stringWithString:(NSString *)theName存儲器地址/位置複製到name或它實際上拷貝從theNamename數據?澄清@property屬性

@interface AddressCard:NSObject 
-(void)setName:(NSString *)theName; 
@end 

@implementation AddressCard 
NSString *name; 
-(void)setName:(NSString *)theName 
{ 
    if(name!=theName) 
    name = [NSString stringWithString:theName]; 
} 
@end 

如果我改變了代碼以下,這是什麼copy有什麼不同?

@interface AddressCard:NSObject 
@property (copy, nonatomic) NSString *name; 
@end 

@implementation AddressCard 
@synthesize name; 
@end 

一般而言,確實copy@property屬性)從一個變量複製數據或拷貝數據的地址到另一個?如果是後一種情況,當變量代表大數據時,我們不會消耗大量內存嗎?

謝謝您的時間和響應!

+3

我覺得你對於「拷貝」的作用感到困惑。它所做的只是向接收方發送「複製」消息,在某些情況下(不可變的'NSStrings或'NSData'),將只返回其自身的保留版本,因爲沒有任何可複製的東西。 –

+0

下面的答案有幫助嗎? – bryanmac

+0

是的。他們非常有幫助。我對延遲承認表示歉意。 –

回答

2

+[NSString stringWithString:]將有效地 '複製' 的字符串。

一般來說,拷貝(@property屬性)拷貝數據的地址還是拷貝數據從一個變量到另一個?

它執行任何對象認爲是copy。它可能會返回一個新的對象,或者它可能會返回它自己。例如,+[NSString stringWithString:]可以只保留返回,如果參數已經是不可改變的自動釋放參數。如果參數是可變的,那麼它將返回一個新的實例,所以你保證有一個不可變的實例。

如果是後一種情況,當變量代表大數據時,我們是不是消耗大量內存?

啊哈 - 但是這招!是的,你最終可能會用副本做出許多新的分配,但訣竅經常是,當你喜歡不可變類型並使用copy時,在大多數情況下,引用計數對象的副本確實很淺。許多集合類型可以簡單地返回自己,如果它們已經是不可變的,或者它們的ivars可以這樣做的話,那麼確保你沒有傳遞可變對象實際上是一個好主意 - 所以儘早創建不可變副本確實可以傳播這個優化,併爲您節省大量的分配(但並非總是如此 - 對於所有這些變體,都會出現一些問題)。

注意:並非所有類都將不變性與可變性區分開來,因此副本並不總是返回不可變對象。

+2

+1有關可變與不可變的更深入的解釋。這是關鍵。 – bryanmac

+0

@bryanmac乾杯:) – justin

+0

@everybody:非常感謝您的回覆。我對延遲承認表示歉意。 –

2

stringWithString將創建一個副本if it's mutable。但請注意since it's not alloc, init, copy方法是自動發佈的。在set方法退出後,您現在持有的副本將在某個時間點變爲poof。如果你改用initWithString,它會創建另一個字符串,但保留它。

副本屬性指的屬性將被分配的發送副本消息中傳遞的對象後返回的對象,這意味着它是由該對象類型來決定如何處理一個副本。對於特定的字符串示例,(副本)將創建一個字符串副本返回給調用者 - 保留副本。這取決於調用者釋放保留的對象。根據memory guidelines,副本將保留該對象。

+0

非常感謝您的回覆Bryanmac。我認爲'stringWithString'是一個類方法,它可以初始化和創建對象。 如果您不介意,請您重新說明您的第二部分回覆。我無法理解它。 –

+0

是的,stringWithString是一個類方法,將創建它,但看到我添加了鏈接的內存指導。它將被自動發佈。複製消息將創建一個保留的對象。 – bryanmac

+1

請注意,如果傳入的字符串是可變的,stringWithString實際上只會複製數據。否則,它將返回遞增的retainCount版本的輸入。 –