我正在查看苹果的样例应用程序EditableDetailView,注意到在其中一个控制器中,他们使用(nonatomic,copy)设置NSString属性的实例。什么时候会使用copy而不是retain?这样做是否是为了能够创建独立的副本而不影响现有数据?
我正在查看苹果的样例应用程序EditableDetailView,注意到在其中一个控制器中,他们使用(nonatomic,copy)设置NSString属性的实例。什么时候会使用copy而不是retain?这样做是否是为了能够创建独立的副本而不影响现有数据?
是的,这样可以在不影响现有数据的情况下生成唯一的副本。合成的setter大致看起来像这样:
// For @synthesize(nonatomic, retain) foo:
- (void) setFoo(NSFoo *theFoo)
{
[theFoo retain]; // retain new value
[foo release]; // release old value, if any
foo = theFoo; // assign new value
}
// For @synthesize(nonatomic, copy) foo:
- (void) setFoo(NSFoo *theFoo)
{
NSFoo* newFoo = [theFoo copy]; // make copy
[foo release]; // release old value, if any
foo = newFoo; // assign new value
}
注意操作的顺序很重要——在进行自我赋值时,必须先保留/复制新值,然后再释放旧值。如果您先释放旧值,然后将属性分配给自身,则可能会意外释放该值。另请注意,如果旧值为 nil
,则向其发送 release
消息是可以的,因为向 nil
对象发送消息是明确允许且不执行任何操作。
保留和复制的选择只是确定对象属性是否与所设置的值共享相同的值。请考虑以下代码:
// suppose the 'foo' property is declared 'retain' and the 'bar' property is
// declared 'copy'
NSFoo *foo = ...;
NSBar *bar = ...;
someObject.foo = foo;
someObject.bar = bar;
[foo changeInternalState]; // someObject.foo also changes, since it's the same object
[bar changeInternalState]; // someObject.bar does NOT change, since it's a copy
copy
方法,您必须重写copyWithZone:
方法。 - geekay由于某些原因,这篇文章出现在我正在回答的后续问题之上。
你的意思是我必须在释放“foo”之前复制“the foo”对象吗?但如果我在复制“the foo”之前释放“foo”,会有什么问题吗?因为它们是两个不同的对象,我不明白为什么释放一个会影响另一个!
大多数情况下,你是正确的。如果它们实际上是两个独立的对象,那就没关系了。问题在于可能会将同一对象重新分配给自身。如果你这样说:
[myObject setFoo: moof];
[myObject setFoo: moof];
然后第二次你这样做时,在复制之前你会释放moof。在此期间,如果moof的保留计数变为零,则moof将被删除,接下来你将没有任何东西可供复制。Foo现在将是nil。
这种情况可能发生吗?可能比你想象的更多。例如,用户有时可能会点击“更新”按钮两次。
我希望这对您有所帮助并且易于理解。
copy
,如NSString
/NSMutableString
,NSArray
/NSMutableArray
,NSDictionary
/NSMutableDictionary
,NSSet
/NSMutableSet
。请参考 @Abizern 的答案这里。 - Kjuly