比方说,我有一个叫做类SomeClass
与string
属性名称:
@interface SomeClass : NSObject { NSString* name; } @property (nonatomic, retain) NSString* name; @end
我知道可能会指定名称,NSMutableString
在这种情况下,这可能会导致错误的行为.
对于字符串一般来说,使用属性是否总是一个好主意copy
而不是retain
?
"复制"属性是否比这种"保留"属性效率低?
Chris Hanson.. 440
对于类型是符合NSCopying
协议的不可变值类的属性,您几乎总是应copy
在@property
声明中指定.指定retain
是在这种情况下你几乎不想要的东西.
这就是你想要这样做的原因:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"]; Person *p = [[[Person alloc] init] autorelease]; p.name = someName; [someName setString:@"Debajit"];
在的当前值Person.name
属性将取决于属性是否被宣布是不同的retain
或copy
-这将是@"Debajit"
,如果属性标记retain
,但@"Chris"
如果该属性被标记copy
.
因为在几乎所有情况下,您都希望防止在其背后改变对象的属性,所以应该标记表示它们的属性copy
.(如果你自己编写setter而不是使用@synthesize
你应该记住实际使用copy
而不是使用retain
它.)
对于类型是符合NSCopying
协议的不可变值类的属性,您几乎总是应copy
在@property
声明中指定.指定retain
是在这种情况下你几乎不想要的东西.
这就是你想要这样做的原因:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"]; Person *p = [[[Person alloc] init] autorelease]; p.name = someName; [someName setString:@"Debajit"];
在的当前值Person.name
属性将取决于属性是否被宣布是不同的retain
或copy
-这将是@"Debajit"
,如果属性标记retain
,但@"Chris"
如果该属性被标记copy
.
因为在几乎所有情况下,您都希望防止在其背后改变对象的属性,所以应该标记表示它们的属性copy
.(如果你自己编写setter而不是使用@synthesize
你应该记住实际使用copy
而不是使用retain
它.)
复制应该用于NSString.如果它是Mutable,那么它会被复制.如果不是,那么它就会被保留下来.确切地说,你在应用程序中想要的语义(让类型做到最好).
对于一般的字符串,使用copy属性而不是retain是否总是一个好主意?
是 - 通常始终使用copy属性.
这是因为您的NSString属性可以传递给NSString实例或NSMutableString实例,因此我们无法确定传递的值是不可变对象还是可变对象.
"复制"属性是否比这种"保留"属性效率低?
如果您的属性正在传递NSString实例,答案是" 否 " - 复制的效率不低于保留.
(效率并不低,因为NSString非常智能,无法实际执行副本.)
如果您的属性传递给NSMutableString实例,那么答案是" 是 " - 复制效率低于保留.
(效率较低,因为必须进行实际的内存分配和复制,但这可能是理想的事情.)
一般来说,"复制"属性可能效率较低 - 但是通过使用NSCopying
协议,可以实现一个"同样有效"的类来保留它.NSString实例就是一个例子.
通常(不仅仅是NSString),什么时候应该使用"copy"而不是"retain"?
copy
当您不希望属性的内部状态在没有警告的情况下更改时,应始终使用.即使对于不可变对象 - 正确编写的不可变对象也会有效地处理复制(请参阅下一节有关不变性的内容NSCopying
).
retain
对象可能存在性能原因,但它带来了维护开销 - 您必须管理内部状态在代码外部更改的可能性.正如他们所说 - 优化最后.
但是,我写的课程是不可改变的 - 我不能只是"保留"它吗?
不 - 使用copy
.如果你的类真的是不可变的,那么最好的做法是实现NSCopying
协议,让你的类在copy
使用时自行返回.如果你这样做:
您班级的其他用户在使用时将获得性能优势copy
.
该copy
注解让自己的代码更易于维护-的copy
注释表明你真的不需要担心这个对象改变别处状态.
我试着遵循这个简单的规则:
我是否希望在将其分配给我的财产时保留对象的价值?使用副本.
我是否想要坚持这个对象,我不关心它的内部价值目前是什么或将来会是什么?使用强(保留).
举例说明:我是否想要坚持"Lisa Miller" 这个名字(副本)或者我想坚持Lisa Miller(强者)这个人?她的名字可能会改为"丽莎史密斯",但她仍然是同一个人.
通过这个例子,复制和保留可以解释如下:
NSMutableString *someName = [NSMutableString stringWithString:@"Chris"]; Person *p = [[[Person alloc] init] autorelease]; p.name = someName; [someName setString:@"Debajit"];
如果属性是复制类型,那么,
将为[Person name]
将保存someName
字符串内容的字符串创建一个新副本.现在对someName
字符串的任何操作都不会起作用[Person name]
.
[Person name]
和someName
字符串将具有不同的内存地址.
但是如果保留,
两者都[Person name]
将保存与somename字符串相同的内存地址,只是somename字符串的保留计数将增加1.
因此,somename字符串中的任何更改都将反映在[Person name]
字符串中.