繁体   English   中英

NSString @property,使用复制而不是保留

[英]NSString @property, using copy instead of retain

我正在查看 Apple 的示例应用程序 EditableDetailView,并注意到在他们的一个控制器中,他们正在使用(非原子,副本)设置 NSString 属性的实例。 什么时候会使用副本而不是保留? 这样他们就可以在不影响现有数据的情况下制作唯一的副本吗?

是的,它可以在不影响现有数据的情况下制作唯一副本。 合成的 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 object 发送消息并且什么也不做。

选择保留还是复制只是决定了对象的属性是否与您设置的值相同。 考虑以下代码:

// 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

请记住,有一个 NS可变字符串。 能够改变其他一些 object 拥有的字符串的内容(例如,通过删除其一半的字符)会非常糟糕,特别是如果您没有意识到您正在影响另一个 object。 因此,最好让其他 object 自己制作副本。

你可能会说“好吧,我为什么不在分配字符串之前复制它呢?”。 也许 object 想要一个可变字符串,而你的字符串是不可变的。 如果必须先复制字符串,则必须在其文档或 header 中查找所需的字符串类型,然后(每次)进行正确的复制。 这样,您只需说other.string = myString ,它就会生成它想要的任何类型的副本——您不必担心它。

(出于某种原因,这篇文章出现在我试图回答的后续问题之上)回复:

你的意思是我必须在发布'foo'之前复制'foo' object?但是如果我在复制'foo'之前释放'foo'会有什么问题?因为它们是两个不同的object我不明白为什么释放一个影响另一个!!!!

大多数时候,你是对的。 事实上,如果它们是两个独立的对象,那就没关系了。 问题在于您可能将相同的 object 分配回自身。 如果你说

[myObject setFoo: moof];
[myObject setFoo: moof];

然后你第二次这样做,你会在复制之前释放 moof。 在此期间,如果 moof 的保留计数变为零,则可能会删除 moof,并且在接下来的步骤中您将没有任何内容可复制。 Foo 现在为零。

这有可能发生吗? 可能比你想象的要多。 例如,有时用户可能会点击两次“更新”按钮。

我希望这是可以理解和有帮助的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM