从另一个对象返回对象时的目标c内存管理

时间:2012-07-09 10:06:12

标签: objective-c memory-management

我在理解记忆管理的一个概念时遇到了问题,因为我对目标C不熟悉。例如,假设我有一个类Bar和Foo。

在主要功能中我打电话:

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];

我知道这是正确的方法。但是为什么我们必须在从另一个对象获取它之后保留它,这是不是意味着返回对象保留计数0?所以我们必须将它重新计算到1才能使用它?但如果它的reatin计数为0,我们怎么知道它仍然存在。我们可以假设,因为它是下一行增加保留计数的对象内存不会被重新定位,但是如果我们有多线程程序呢?

2 个答案:

答案 0 :(得分:3)

当一个类方法返回一个对象时,它会autorelease它,所以你不必费心;典型地:

- (Foo *)getFoo
{
    return [[_foo retain] autorelease];
}

如果您在调用方法的生命周期内仅使用foo,则不需要retain它,因为直到下次通过时才会autorelease运行循环,所以你的代码应该是:

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];

但是,如果您希望暂停foo一段时间,超出调用方法的范围,则需要retain它,然后再release

还有一件事; getter方法名称的约定只是“name”,因此你的setter应该是setFoo而你的getter将是foo。遵守命名约定是一个好主意,因为它可以让你知道方法的作用,比如7个月的时间,静态分析等工具可以理解约定。

答案 1 :(得分:0)

方法getFoo不会返回具有0保留计数的对象。它返回一个 +0保留计数的对象,这意味着:

  • 对象的保留计数不为空(否则,该对象将不存在)
  • 并且保留计数没有被方法的调用改变,或者如果是,则是以平衡的方式改变(与release一样多autorelease / retain / alloc / new / copy)。

因此,对象的生命周期完全取决于保留的位置和方式。我们不知道对象有多长时间,因为任何方法调用都可以释放对象。

例如,让我们考虑以下代码:

id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];

当我们删除它时,数组不再保留对象anObject。因此它可能已被破坏(但可能不是因为它仍在其他地方使用)。

通常,从方法(alloccopynewretain)获取对象时,我们可以假设:

  • 要么保留对象,要么自动释放,
  • 对象由返回它的对象保留。

因此我们知道对象foo在我们从当前方法/函数返回之前是有效的,或者我们调用一个方法/函数来改变对象bar的状态,以先到者为准。在那之后,它可能已被破坏。

因此,在您的情况下,您可以安全地省略retain / release对。

但是,除非我们知道我们调用的每个方法的实现,否则很难保证对象不会被释放。因此,保留(然后释放)我们获得的每个对象是更安全的方法,这就是编译器在启用ARC(自动引用计数)时将要执行的操作。

但是这需要你编写很多retain / release,你的代码将难以阅读,理解和维护。此外,您编写的代码越多,您获得的错误就越多(除非您从不编写错误)。

总之,除非你有理由怀疑它可能会消失,否则你不需要保留一个物体。