- (void)setSomeInstance:(SomeClass *)aSomeInstanceValue
{
if (someInstance == aSomeInstanceValue)
{
return;
}
SomeClass *oldValue = someInstance;
someInstance = [aSomeInstanceValue retain];
[oldValue release];
}
好的,所以setter应该看起来像。我理解前三行——当新对象和旧对象相同时,防止出现之前的情况。但是这条线呢:
SomeClass *oldValue = someInstance;
为什么系统必须保留旧对象的地址。为什么不能简单的
[someinstance release];
someinstance = [aSomeInstanceValue retain];
实际上-没有原因。
这通常只是一种选择。
有三个用于书写访问者的习语。
自动发布:
- (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,然后再使用release,如果分析显示存在瓶颈,请使用check first方法。
我建议默认的retain setter的工作方式如下:
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
如果你不检查旧的和新的foo是否相同,如果你出于某种原因写了这样的东西,你可能会引用一个被释放的对象:
myObject.foo = myObject.foo;
因为同一个对象会先被释放,然后被保留。如果myObject是唯一的所有者,那么该对象将在第一次发布后被释放,留下一个悬空指针。
默认的保留设置程序的工作方式如下:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}