12

例子:

- (NSString*) title {
    return [[title retain] autorelease];
}

二传手实际上已经保留了它,对吗?实际上没有人应该绕过 Setter ......所以我想知道为什么 getter 不只是返回对象?它实际上已经保留了。或者如果同时另一个对象被传递给setter,是否需要这样做?

4

4 回答 4

12

从这里http://www.macosxguru.net/article.php?story=20030713184140267

- (id)getMyInstance
    {
        return myInstanceVar ;
    }

或者

- (id)getMyInstance
{
    return [[myInstanceVar retain] autorelease] ;
}

有什么不同 ?第二个允许调用者获取容器对象的实例变量,处置容器并继续使用实例变量直到当前自动释放池的下一次释放,而不会受到间接产生的实例变量释放的伤害通过释放其容器:

aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);

如果“get”是以第一种形式实现的,你应该写:

aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];

第一种形式在代码执行速度方面效率更高一些。但是,如果您正在编写供他人使用的框架,也许应该推荐第二个版本:它使使用您的框架的人的生活更轻松:他们不必过多考虑自己在做什么……; ) 如果您选择第一个样式版本,请在文档中明确说明……无论您选择哪种方式,请记住,从版本 1 更改为版本 2 是为了保存客户端代码,当从版本 2 回到版本 1 时会破坏现有的客户端代码……</p>

于 2009-04-29T11:30:03.527 回答
7

这不仅适用于有人释放容器的情况,因为在这种情况下,他们应该自己保留对象更明显。考虑这段代码:

NSString* newValue = @"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue

这看起来很合理,但是如果 setter 和 getter 都没有使用 autorelease,那么“继续做某事”部分可能会崩溃,因为 oldValue 现在已被释放(假设没有其他人保留它)。您通常希望使用Apple 的访问器方法示例中的技术 1 或技术 2,因此上述代码将按照大多数人的预期工作。

于 2009-04-29T20:32:49.247 回答
4

比较这段代码

  return [[title retain] release]; // releases immediately

有了这个

  return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)

第二个保证客户端将有一个未释放的对象可以使用。

这在这样的情况下很有用(客户端代码):

 NSString *thing = [obj title];
 [obj setTitle:nil]; // here you could hit retainCount 0!
 NSLog(@"Length %d", [thing length]); // here thing might be dealloced already!

您的方法中的保留(和使用的autorelease代替releasetitle可防止此代码爆炸。release在当前调用堆栈执行完毕(当前运行循环结束)之前,自动释放的对象不会调用其方法。这使调用堆栈中的所有客户端代码都有机会使用此对象,而不必担心它会被释放。

要记住的重要事项:这不是 Java、Ruby 或 PHP。仅仅因为你在你的 [原文如此] 变量中有一个对象的引用并不能确保你不会从你下面得到它。你必须保留它,但你必须记得释放它。自动释放可以避免这种情况。您应该始终使用自动释放,除非您正在处理具有多次迭代的属性或循环(除非出现问题,否则可能甚至不会)。

于 2011-05-18T04:34:29.083 回答
0

我以前从未见过这种模式,但对我来说似乎毫无意义。如果客户端代码在父对象上调用“释放”,我想目的是保持返回值的安全。它并没有真正伤害任何东西,但我怀疑这种情况经常出现在精心设计的库中。


喔好吧。从 smorgan 链接到的文档来看,这似乎是苹果目前推荐人们使用的方法之一。我想我还是更喜欢老派的版本:

- (NSString *) value
{
    return myValue;
}

- (void) setValue: (NSString *) newValue
{
    if (newValue != myValue)
    {
       [myValue autorelease]; // actually, I nearly always use 'release' here
       myValue = [newValue retain];
    }
}
于 2009-04-29T19:13:59.187 回答