2011-11-03 47 views
6

我看到很多討論說我應該使用副本 NSString屬性,因爲它會阻止他人改變我的背後。但那麼爲什麼我們不只是設置只讀屬性呢?NSString屬性複製或只讀?

更新

謝謝回答我的問題。但事情是,對於NSString屬性,你總是不希望別人修改它,對吧?你可以自己修改它,但絕對不是別人。我想大部分時間NSString都會設置它的初始值(無論是由您還是其他人),之後只有您會修改它。那麼,爲什麼不只是使用只讀屬性

其實我大多數時間使用複製。但後來我意識到大部分時間我只在init方法中使用這些setter。所以我認爲我應該只使用readonly而不是複製這些情況。所以讓我以這種方式提出問題:如果你只在你的init方法中爲你的NSString使用那些setter,那麼你應該使用readonly來代替。這是一個合理的結論嗎?

回答

10

如果你只在你的init方法中爲你的NSString使用那些setter,那麼你應該使用readonly。這是一個合理的結論嗎?

由於不應使用在部分構造的狀態(init/dealloc)訪問,則應該將它聲明爲copyreadonly,然後執行在初始化複製:

- (id)initWithName:(NSString *)inName 
{ 
    self = [super init]; 
    if (0 != self) { 
    name = [inName copy]; 
    } 
    return self; 
} 

更詳細地,copyreadonly在語義上是不同的概念。

  • 您使用copy,因爲您對大多數情況下的值感興趣。這也是使用不可變字符串的保障和優化。

  • 您使用readonly來禁止客戶端變異/設置您的數據。

一起,他們提供了一個良好的安全程度,但僅憑:

  • copy仍然允許客戶在通過二傳手程序的執行任意點的設定值。

  • readonly並不意味着copy和保留的性質可能會在你背後來改變;考慮當你傳遞一個可變的變體時會發生什麼,並且在調用setter之後客戶端會改變它。

最安全的方法是使用copyreadonly

  • 很明顯,你會使用readwrite,當你需要提供一個setter給您的客戶,你支持這種變化。

  • 保留一個字符串(或數組,或...)而不是複製通常是一個壞主意。對於您不復制這些類型的用途很少有用處,並且可能導致細微的錯誤。即使在處理可變類型時,通常也需要一個可變副本(編譯器不會爲你合成)。保留或分配這些類型幾乎從來不是你想要的。我所做的一個例外是在處理大量分配時,數據被很好地封裝(例如,我將所有權從一個地方轉移到另一個地方以避免複製)的重量較大的NSMutableData實例。

+0

感謝您更新我的問題。 – Qiulang

+0

不客氣=) – justin

+1

「最安全的方法是使用複製和只讀」。但是,這不是讓你的客戶感到困惑嗎?只讀意味着沒有setter,而複製意味着有setter?當然你的客戶會進一步推斷你在你的.m文件中添加了readwrite,但是聲明copy和readonly仍然讓我一見鍾情。 – Qiulang

6

如果你不希望別人修改你的財產,那麼你絕對應該標記它readonly。當他們說使用copy時,意思是字符串不能在背後改變,如果某人給你的屬性指定了一個字符串,並且該字符串是可變的,然後他們改變了字符串,當你以後訪問你的屬性時我會找回更改字符串。但是,如果你使用copy,那麼你會得到一個字符串如何分配給屬性的時間的快照(這是人們期望發生的事情)。

+0

感謝您回答我的問題。但事情是,對於NSString屬性,你總是不希望別人修改它,對吧?其他人可以設置這些NSString的首字母縮寫值,但是你不希望他們修改它,對嗎? – Qiulang

+1

@Qiulang:很多時候,你確實希望別人能夠分配給你的房產。這實際上取決於你的班級正在做什麼以及屬性代表什麼。 –

0

你可以同時做。因爲NSString是不可變的,所以底層字符串不能被改變。你可能不希望引用改變,這就是你只能使用readonly的原因。

複製僅適用於setter,getter仍然會返回一個引用而不是副本。