Iphone iOS中的默认设置程序
好的,所以塞特应该是这样的。我理解前3行-防止新对象与旧对象相同时的情况。 但是这一行呢:Iphone iOS中的默认设置程序,iphone,memory-management,Iphone,Memory Management,好的,所以塞特应该是这样的。我理解前3行-防止新对象与旧对象相同时的情况。 但是这一行呢: - (void)setSomeInstance:(SomeClass *)aSomeInstanceValue { if (someInstance == aSomeInstanceValue) { return; } SomeClass *oldValue = someInstance; someInstance = [aSomeInstanceValue retain]; [oldVa
- (void)setSomeInstance:(SomeClass *)aSomeInstanceValue
{
if (someInstance == aSomeInstanceValue)
{
return;
}
SomeClass *oldValue = someInstance;
someInstance = [aSomeInstanceValue retain];
[oldValue release];
}
为什么系统必须保留旧对象的地址。为什么不能简单一点呢
SomeClass *oldValue = someInstance;
默认的retain setter的工作原理如下:
[someinstance release];
someinstance = [aSomeInstanceValue retain];
默认的retain setter的工作原理如下:
[someinstance release];
someinstance = [aSomeInstanceValue retain];
我建议默认的retain setter的工作方式如下:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
如果您不检查新旧foo是否相同,那么如果出于某种原因编写以下内容,您可能最终会得到对解除分配对象的引用:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
因为同一个对象将首先被释放,然后被保留。如果myObject是唯一的所有者,那么在第一个版本之后,对象将被释放,留下一个悬空的指针。我建议默认的retain setter的工作方式如下:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
如果您不检查新旧foo是否相同,那么如果出于某种原因编写以下内容,您可能最终会得到对解除分配对象的引用:
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
因为同一个对象将首先被释放,然后被保留。如果myObject是唯一的所有者,那么该对象将在第一次发布后被解除分配,留下一个悬空的指针。实际上-没有理由
这通常只是一种选择
有三种编写访问器的习惯用法
自动释放:
myObject.foo = myObject.foo;
要编写的代码更少,但我认为在这种情况下自动释放是懒惰
保留然后释放
- (void)setFoo:(id)newFoo {
[foo autorelease];
foo = [newFoo retain];
}
先检查
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
最后两种方法之间的唯一区别是,第二种方法在尝试设置属性之前检查新值是否与当前值不同。以额外的if声明为代价。因此-如果新值可能与旧值相同,则使用此构造可以提供更好的性能
通常,如果出于某种奇怪的原因没有使用属性,请使用retain-then-release,如果分析显示存在瓶颈,则使用check-first方法。实际上-没有原因
这通常只是一种选择
有三种编写访问器的习惯用法
自动释放:
myObject.foo = myObject.foo;
要编写的代码更少,但我认为在这种情况下自动释放是懒惰
保留然后释放
- (void)setFoo:(id)newFoo {
[foo autorelease];
foo = [newFoo retain];
}
先检查
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
最后两种方法之间的唯一区别是,第二种方法在尝试设置属性之前检查新值是否与当前值不同。以额外的if声明为代价。因此-如果新值可能与旧值相同,则使用此构造可以提供更好的性能
通常,如果出于某种奇怪的原因没有使用属性,请使用retain-then-release,如果分析显示存在瓶颈,则使用check-first方法。无需检查nil,因为向nil发送消息会立即返回nil。那么如果_foo==aFood呢?默认setter不是这样工作的,原因正是@juantorena确定的。检查nil是不必要的,因为向nil发送消息会立即返回nil。那么如果_foo==aFood呢?默认setter的工作原理与@juantorena确定的完全不同。我会让最后一句话更有力;如果setter没有特殊行为,则应始终使用@property和@synthesis。如果您的setter有特殊的行为,您应该认真地重新考虑您的体系结构。在不断发展的代码库中,具有自定义行为的setter是一个永无止境的痛苦来源。如果一个对象在属性更改时需要以其他方式进行更新,那么该对象呢?我经常使用它,从来没有遇到过严重的问题。使用自定义setter和getter有很多原因。保罗·赫加蒂在他的课程中给出了很多例子。确保未设置的值的默认值为1。-(CGFloat)scale{if(!\u scale){return DEFAULT\u scale;//不允许零scale}否则{return\u scale;}}我会让最后一句话更有力;如果setter没有特殊行为,则应始终使用@property和@synthesis。如果您的setter有特殊的行为,您应该认真地重新考虑您的体系结构。在不断发展的代码库中,具有自定义行为的setter是一个永无止境的痛苦来源。如果一个对象在属性更改时需要以其他方式进行更新,那么该对象呢?我经常使用它,从来没有遇到过严重的问题。使用自定义setter和getter有很多原因。保罗·赫加蒂在他的课程中给出了很多例子。确保未设置的值的默认值为1。-(CGFloat)scale{if(!\u scale){return DEFAULT\u scale;//不允许零scale}否则{return\u scale;}