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).
If you don't want others to modify your property, then you absolutely should mark it readonly
. What people mean when they say using copy
means the string can't be changed behind your back is, if someone assigns a string to your property, and the string is mutable, and then they mutate the string, when you later access your property you'll get back the changed string. But if you use copy
then you'll get back a snapshot of how the string looked at the time it was assigned to the property (which is what people expect to happen).