我在理解记忆管理的一个概念时遇到了问题,因为我对目标C不熟悉。例如,假设我有一个类Bar和Foo。
在主要功能中我打电话:
Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];
我知道这是正确的方法。但是为什么我们必须在从另一个对象获取它之后保留它,这是不是意味着返回对象保留计数0?所以我们必须将它重新计算到1才能使用它?但如果它的reatin计数为0,我们怎么知道它仍然存在。我们可以假设,因为它是下一行增加保留计数的对象内存不会被重新定位,但是如果我们有多线程程序呢?
答案 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
。因此它可能已被破坏(但可能不是因为它仍在其他地方使用)。
通常,从方法(alloc
,copy
,new
或retain
)获取对象时,我们可以假设:
因此我们知道对象foo
在我们从当前方法/函数返回之前是有效的,或者我们调用一个方法/函数来改变对象bar
的状态,以先到者为准。在那之后,它可能已被破坏。
因此,在您的情况下,您可以安全地省略retain
/ release
对。
但是,除非我们知道我们调用的每个方法的实现,否则很难保证对象不会被释放。因此,保留(然后释放)我们获得的每个对象是更安全的方法,这就是编译器在启用ARC(自动引用计数)时将要执行的操作。
但是这需要你编写很多retain
/ release
,你的代码将难以阅读,理解和维护。此外,您编写的代码越多,您获得的错误就越多(除非您从不编写错误)。
总之,除非你有理由怀疑它可能会消失,否则你不需要保留一个物体。