假设我有一个名为SomeClass的类,它有一个字符串属性名:
@interface SomeClass : NSObject
{
NSString* name;
}
@property (nonatomic, retain) NSString* name;
@end
我知道,名字可以被分配一个NSMutableString在这种情况下,这可能会导致错误的行为。
对于一般的字符串,使用copy属性而不是retain属性总是一个好主意吗?
“复制”的属性是否比“保留”的属性效率低?
@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
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];
当然,当设计包含该属性的对象时,只有你知道是否设计受益于赋值复制的模式- Cocoawithlove.com有以下说法:
“当setter参数可能是可变的,但你不能在没有警告的情况下改变属性的内部状态时,你应该使用复制访问器”——因此,关于你是否能忍受值意外变化的判断完全是你自己的。想象一下这个场景:
//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.
在这种情况下,不使用copy,我们的contact对象自动接受新值;但是,如果我们确实使用了它,我们必须手动确保检测到更改并同步。在这种情况下,保留语义可能是可取的;在另一种情况下,copy可能更合适。
通过这个例子,复制和保留可以这样解释:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:@"Debajit"];
如果属性的类型是copy,则,
将为[Person name]字符串创建一个新的副本,该副本将包含someename字符串的内容。现在对someename字符串的任何操作都不会对[Person name]产生影响。
[Person name]和someename字符串将有不同的内存地址。
但是在保留的情况下,
[Person name]将与someename字符串拥有相同的内存地址,只是someename字符串的保留计数将增加1。
因此,someename字符串中的任何更改都将反映在[Person name]字符串中。