I see many discussions saying that I should use copy for NSString property because it will prevent others from changing it behind my back. But then why don\'t w
if you only use those setters for your NSStrings in your init method, then you should use readonly instead. Is this a reasonable conclusion?
Since you should not use accessors in partially constructed states (init
/dealloc
), then you should declare it as copy
and readonly
, then perform the copy in the initializer:
- (id)initWithName:(NSString *)inName
{
self = [super init];
if (0 != self) {
name = [inName copy];
}
return self;
}
In more detail, copy
and readonly
are semantically different concepts.
You use copy
because you are interested in the value in most cases. It's also a safeguard and an optimization to use immutable strings.
You use readonly
to prohibit clients from mutating/setting your data.
Together, they provide a good degree of safety, but alone:
copy
still allows clients to set the value at any point in the program's execution via the setter.
readonly
does not imply copy
, and a retained property could be changed behind your back; consider what happens when you are passed a mutable variant and the client mutates it after calling the setter.
The safest way is to use copy
and readonly
.
obviously, you will use readwrite
when you need to provide a setter to your clients, and you support that change.
retaining a string (or array, or...) instead of copying is usually a bad idea. there is rarely a good use for you not to copy these types, and it can lead to subtle errors. even when you are dealing with a mutable type, you'll usually want a mutable copy (which the compiler will not synthesize for you). retaining or assigning these types is almost never what you want. one exception i make is when dealing with large allocations, where the data is encapsulated well (e.g. a heavy NSMutableData
instance which I pass ownership from one place to another to avoid a copy).