- (void)setSomeInstance:(SomeClass *)aSomeInstanceValue
{
if (someInstance == aSomeInstanceValue)
{
return;
}
SomeClass *oldValue = someInstance;
someInstance = [aSomeInstanceValue retain];
[oldValue release];
}
好的,所以setter应该是这样的。我理解前3行 - 在新对象与旧对象相同的情况下防止。
但是这一行怎么样:
SomeClass *oldValue = someInstance;
为什么系统必须保留旧对象的地址。为什么不能简单地
[someinstance release];
someinstance = [aSomeInstanceValue retain];
答案 0 :(得分:2)
我建议默认的retain setter工作方式如下:
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
如果你不检查旧的和新的foo是否相同,如果你出于某种原因写了这样的东西,你最终可能会引用一个解除分配的对象:
myObject.foo = myObject.foo;
因为首先会释放相同的对象,然后保留。如果myObject是唯一的所有者,那么在第一次发布之后该对象将被释放,留下一个悬空指针。
答案 1 :(得分:2)
实际上 - 没有理由。
这通常只是一种选择。
写作访问器有三种习语。
<强>自动释放强>:
- (void)setFoo:(id)newFoo {
[foo autorelease];
foo = [newFoo retain];
}
写的代码较少,但我认为在这种情况下自动释放是懒惰的。
保留然后发布
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
先检查
- (void)setFoo:(id)newFoo {
if ([foo isEqual:newFoo]) {
return;
}
[foo release];
foo = [newFoo retain];
}
最后两个之间的唯一区别是第二个检查是在尝试设置属性之前检查新值是否与当前值不同。以额外的if语句为代价。所以 - 如果新值可能与旧值相同,使用这种结构可以提供更好的性能。
通常,如果您因某些奇怪的原因没有使用属性,请使用retain然后释放,然后如果分析显示存在瓶颈 - 请使用check first方法。
答案 2 :(得分:0)
默认的retain setter的工作原理如下:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}