Let\'s say I have a class called SomeClass
with a string
property name:
@interface SomeClass : NSObject
{
NSString* name;
}
@p
Surely putting 'copy' on a property declaration flies in the face of using an object-oriented environment where objects on the heap are passed by reference - one of the benefits you get here is that, when changing an object, all references to that object see the latest changes. A lot of languages supply 'ref' or similar keywords to allow value types (i.e. structures on the stack) to benefit from the same behaviour. Personally, I'd use copy sparingly, and if I felt that a property value should be protected from changes made to the object it was assigned from, I could call that object's copy method during the assignment, e.g.:
p.name = [someName copy];
Of course, when designing the object that contains that property, only you will know whether the design benefits from a pattern where assignments take copies - Cocoawithlove.com has the following to say:
"You should use a copy accessor when the setter parameter may be mutable but you can't have the internal state of a property changing without warning" - so the judgement as to whether you can stand the value to change unexpectedly is all your own. Imagine this scenario:
//person object has details of an individual you're assigning to a contact list.
Contact *contact = [[[Contact alloc] init] autorelease];
contact.name = person.name;
//person changes name
[[person name] setString:@"new name"];
//now both person.name and contact.name are in sync.
In this case, without using copy, our contact object takes the new value automatically; if we did use it, though, we'd have to manually make sure that changes were detected and synced. In this case, retain semantics might be desirable; in another, copy might be more appropriate.
@interface TTItem : NSObject
@property (nonatomic, copy) NSString *name;
@end
{
TTItem *item = [[TTItem alloc] init];
NSString *test1 = [NSString stringWithFormat:@"%d / %@", 1, @"Go go go"];
item.name = test1;
NSLog(@"-item.name: point = %p, content = %@; test1 = %p", item.name, item.name, test1);
test1 = [NSString stringWithFormat:@"%d / %@", 2, @"Back back back"];
NSLog(@"+item.name: point = %p, content = %@, test1 = %p", item.name, item.name, test1);
}
Log:
-item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0
+item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660
Since name is a (immutable) NSString
, copy or retain makes no difference if you set another NSString
to name. In another word, copy behaves just like retain, increasing the reference count by one. I think that is an automatic optimization for immutable classes, since they are immutable and of no need to be cloned. But when a NSMutalbeString
mstr
is set to name, the content of mstr
will be copied for the sake of correctness.
If the string is very large then copy will affect performance and two copies of the large string will use more memory.