我看到很多讨论说我应该使用复制来获取NSString属性,因为它会阻止其他人在我背后更改它。但那么为什么我们不为它设置 readonly 属性呢?
更新
感谢您回答我的问题。但问题是,对于NSString属性,你总是不希望别人修改它,对吧?您可以自己修改它,但绝对不能修改其他人。我猜大多数时候NSString都会设置它的初始值(由你或其他人设置),之后只有你会修改它。那么为什么不只使用readonly属性
实际上我大部分时间都在使用副本。但后来我发现大部分时间我只在init方法中使用那些setter。所以我认为我应该使用readonly而不是copy来处理这些情况。
因此,让我以这种方式提出问题:如果您只在init方法中使用这些setter作为NSStrings,那么您应该使用readonly。这是一个合理的结论吗?
答案 0 :(得分:12)
如果您只在init方法中为NSStrings使用这些setter,那么您应该使用readonly。这是一个合理的结论吗?
由于您不应在部分构造状态(init
/ dealloc
)中使用访问器,因此您应将其声明为copy
和readonly
,然后执行复制初始化器:
- (id)initWithName:(NSString *)inName
{
self = [super init];
if (0 != self) {
name = [inName copy];
}
return self;
}
更详细地说,copy
和readonly
在语义上是不同的概念。
您使用copy
因为您对大多数情况下的值感兴趣。它也是使用不可变字符串的安全措施和优化。
您使用readonly
禁止客户变更/设置您的数据。
它们共同提供了一定程度的安全性,但仅此一项:
copy
仍允许客户通过设置器在程序执行的任何位置设置值。
readonly
并不意味着copy
,并且可以在您的背后更改保留的财产;考虑当你传递一个可变变量时会发生什么,并且客户端在调用setter之后会改变它。
最安全的方法是使用copy
和readonly
。
显然,当您需要为客户提供设置器时,您将使用readwrite
,并且您支持该更改。
保留字符串(或数组,或......)而不是复制通常是一个坏主意。很难有一个很好的用途,你不要复制这些类型,它可能会导致微妙的错误。即使你正在处理一个可变类型,你通常也会想要一个可变副本(编译器不会为你合成)。保留或分配这些类型几乎不是你想要的。我所做的一个例外是处理大量分配时,数据封装得很好(例如,我将所有权从一个地方传递到另一个地方以避免复制的重NSMutableData
个实例。
答案 1 :(得分:6)
如果您不希望其他人修改您的媒体资源,那么您绝对应该将其标记为readonly
。人们说使用copy
意味着字符串不能在你的背后改变是什么意思,如果有人为你的属性分配一个字符串,并且字符串是可变的,然后他们改变字符串,当你以后访问您的媒体资源,您将获得已更改的字符串。但是如果您使用copy
,那么您将获得一个快照,了解字符串在分配给该属性时的状态(这是人们期望发生的事情)。