假设我有一个名为SomeClass的类,它有一个字符串属性名:
@interface SomeClass : NSObject
{
NSString* name;
}
@property (nonatomic, retain) NSString* name;
@end
我知道,名字可以被分配一个NSMutableString在这种情况下,这可能会导致错误的行为。
对于一般的字符串,使用copy属性而不是retain属性总是一个好主意吗?
“复制”的属性是否比“保留”的属性效率低?
通过这个例子,复制和保留可以这样解释:
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]字符串中。
对于类型为符合NSCopying协议的不可变值类的属性,你几乎总是应该在@property声明中指定copy。在这种情况下,几乎不需要指定retain。
以下是你想这么做的原因:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:@"Debajit"];
Person.name属性的当前值将根据属性被声明为retain还是copy而有所不同——如果属性被标记为retain,则为@"Debajit",但如果属性被标记为copy,则为@"Chris"。
因为在几乎所有情况下,您都希望防止在背后改变对象的属性,所以应该将表示它们的属性标记为copy。(如果你自己编写setter,而不是使用@synthesize,你应该记得在其中使用copy而不是retain。)
对于一般的字符串,使用copy属性而不是retain属性总是一个好主意吗?
是的——通常总是使用copy属性。
这是因为NSString属性可以传递一个NSString实例或一个NSMutableString实例,因此我们不能真正确定传递的值是一个不可变对象还是可变对象。
“复制”的属性是否比“保留”的属性效率低?
If your property is being passed an NSString instance, the answer is "No" - copying is not less efficient than retain.
(It's not less efficient because the NSString is smart enough to not actually perform a copy.)
If your property is passed an NSMutableString instance then the answer is "Yes" - copying is less efficient than retain.
(It's less efficient because an actual memory allocation and copy must occur, but this is probably a desirable thing.)
Generally speaking a "copied" property has the potential to be less efficient - however through the use of the NSCopying protocol, it's possible to implement a class which is "just as efficient" to copy as it is to retain. NSString instances are an example of this.
一般(不只是NSString),什么时候我应该使用“复制”而不是“保留”?
当您不希望属性的内部状态在没有警告的情况下发生变化时,应该始终使用copy。即使对于不可变对象,正确编写的不可变对象也可以有效地处理复制(参见下一节关于不可变性和NSCopying)。
保留对象可能是出于性能方面的考虑,但这带来了维护开销——您必须管理内部状态在代码外部更改的可能性。正如他们所说,最后优化。
但是,我把我的类写成了不可变的——难道我不能“保留”它吗?
无用的拷贝。如果你的类真的是不可变的,那么最好的做法是实现NSCopying协议,让你的类在使用copy时返回自己。如果你这样做:
类的其他用户在使用copy时将获得性能优势。
复制注释使您自己的代码更易于维护——复制注释表明您确实不需要担心该对象在其他地方改变状态。