成为Cocoa / Obj-C新手我正在阅读Aaron Hillegass的“Cocoa Programming for Mac OS X”一书,并且 - 现在我们还有机会使用GC避免所有这些推理 - 我不确定我是否得到了其中一些保留的原因。
特别是在其中一个例子中,Aaron提供了良好的编程实践:
- (void) setFoo:(NSCalendarDate *)x
{
[x retain];
[foo release];
foo = x;
}
我没有理由在方法的第一行保留x实例:
[x retain];
这个实例的范围只是set方法,对吧? 当退出方法范围时,x实例应该被解除分配吗? 此外,在将x分配给foo时:
foo = x;
foo无论如何指向x内存单元格,因此会增加指向对象的保留计数,不是吗?这应该确保不会释放内存。
那么,有什么意义呢?当然,我确信我错过了什么,但不知道到底是什么。
谢谢, 的Fabrizio
答案 0 :(得分:11)
保留意味着:我将需要此对象保持不变,不得取消分配。如果不保留x
,则可能发生以下情况:
您将x
分配给foo
,因此foo
现在指向您的NSCalendarDate所在的地址。有人释放或自动释放此对象,它的保留计数最终会降为0并且对象被取消分配。现在您的foo
仍指向该地址,但不再是有效对象。稍后,会创建一个新对象,并且它与旧的NSCalendarDate对象位于同一地址。现在你的foo
指向一个完全不同的对象!
为了防止这种情况,您需要retain
它。你需要说,请不要释放对象,我需要它。一旦你完成了它,你release
就意味着我不再需要这个对象了,如果没有其他人需要,你可以立即清理它。
现在为经典的三部分作业。考虑一下您的setFoo:
将如下所示:
- (void) setFoo:(NSCalendarDate *)x
{
[foo release];
[x retain];
foo = x;
}
这是一个非常糟糕的主意。考虑您的对象是唯一保留NSCalendarDate对象的对象,并考虑您将执行:[self setFoo:foo];
。可能听起来很傻,但这样的事情可能会发生。流程现在是这样的:
foo
将被释放。它的保留计数现在可能会降至0并且对象将被释放。这就是为什么你总是先retain
新对象,然后release
旧对象。
如果您来自Java或.NET背景,了解类型Foo *
的变量仅包含对象的地址非常重要,仅此而已。在Java或.NET中,如果愿意,指向对象的变量会自动“保留”它。 Objective-C不是这样(在非GC环境中)。您可以将Foo *
类型的变量视为弱引用,并且明确需要告诉Objective-C您是否仍然需要该地址处的该对象。