Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSString property copy or readonly?

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 ?

like image 391
Qiulang 邱朗 Avatar asked Nov 03 '11 03:11

Qiulang 邱朗


2 Answers

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

like image 164
justin Avatar answered Nov 15 '22 13:11

justin


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

like image 45
Lily Ballard Avatar answered Nov 15 '22 15:11

Lily Ballard