I started a small Xcode project to investigate whether an NSMutableString
property should be copy
or retain
. I declared my property with the copy
attribute:
@property (nonatomic,copy) NSMutableString *stringA;
Then initialized it as self.stringA = [NSMutableString new];
finally tried to set a string [stringA setString:@"A"];
.
However the program gives,
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with setString:'"
Is it because the resulting string is a NSString
? Does this mean I should declare my NSMutableString
properties using retain
attribute and NSString
properties using copy
?
You're right, the
copy
method ofNSMutableString
returns an immutableNSString
. This is a convention in Cocoa, it also applies toNSMutableArray
,NSMutableDictionary
, etc.So if you want your property to remain mutable, you should declare it as
retain
. If you need copy semantics, but still want the result to be mutable, you'd have to implement your own setter for the property (and usemutableCopy
to do the copying).The reason you commonly see
copy
for string properties is that it's often desirable to have a guarantee that a string is immutable, regardless of what kind of string is assigned to the property. Otherwise you might end up accidentally modifying the same string elsewhere, which can be difficult to debug. Immutable objects also have the benefit of being thread-safe.