6

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 we just set readonly property for it?

Update

Thanks for answering my question. But the thing is that for NSString property, you always don't want others to modify it, right? You may modify it yourself but definitely not others. I guess most of time NSString get its initial value set up (either by you or by others), after that only you will modify it. Then why not just use readonly property

Actually I use copy most of time. But then I realize most of time I only use those setters in my init method. So I think I should use readonly instead of copy for those case.

So let me ask question in this way: if you only use those setters for your NSStrings in your init method, then you should use readonly instead. Is this a reasonable conclusion ?

justin
  • 104,054
  • 14
  • 179
  • 226
Qiulang
  • 10,295
  • 11
  • 80
  • 129

2 Answers2

12

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).

justin
  • 104,054
  • 14
  • 179
  • 226
  • 1
    "The safest way is to use copy and readonly". But isn't that confused your client ? readonly means no setter, while copy mean having a setter? Of course your client will further infer that you add readwrite in your .m file, but declaring copy and readonly still makes me confused at the first sight. – Qiulang Nov 03 '11 at 04:58
  • OK I got it. Property declared as copy, retain has no relevance to users of the class. It is for implementation purpose. I will accept your answer. Thanks again! – Qiulang Nov 03 '11 at 05:49
  • @Qiulang I still declare it `copy` because it documents that the value is an immutable value, and because I am used to seeing NSString properties as `copy`. You're welcome. – justin Nov 03 '11 at 06:02
6

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).

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • Thanks for answering my question. But the thing is that for NSString property, you always don't want others to modify it, right? Others can set those NSStrings initials values, but you don't want them to modify it, right ? – Qiulang Nov 03 '11 at 04:25
  • 1
    @Qiulang: Quite frequently, you do want others to be able to assign to your properties. It really depends on what your class is doing and what the property represents. – Lily Ballard Nov 03 '11 at 05:24