自动释放池在Cocoa Touch中什么时候会导致对象被释放?

11

我理解你需要在iOS上小心使用autorelease。我有一个方法,它返回一个由调用者所需的对象 alloc,在这种情况下——就我所知——我需要在返回对象之前向被调用方发送 autorelease

这很好,但一旦控制返回到手机(即处理完我的按钮单击后),似乎自动释放池就被释放了。我怀疑这就是它应该的方式,但我想知道在这种情况下的最佳做法是什么。

我已经从调用者发送了一个 retain 消息,这样对象就不会被释放,并在 dealloc 中显式释放它。

这是最好的方法吗?

5个回答

21

自动释放池(typically),通常会在每次运行循环(iteration)之后被释放(release)。大致上,每个Cocoa和Cocoa Touch应用程序的结构都是这样的:

Get the next message out of the queue
Create an autorelease pool
Dispatch the message (this is where your application does its work)
Drain the autorelease pool

你所描述的是预期行为。如果你想使一个对象在这之后继续存在,你需要显式地保留它。


13

使用autorelease是一种表示:“对象,我不再需要你了,但我会把你传递给其他可能需要你的人,所以不要马上消失。” 因此,对象将保持足够的时间,以便您可以从方法中返回它或将其给另一个对象。当某些代码想要保留该对象时,必须通过retain来声明所有权。

请参阅内存管理指南了解使用autorelease的正确方式所需的所有信息。


好的回答,但是__这是否安全__?你有没有遇到过这样的情况:当你返回一个使用[[[object alloc] init] autorelease]方法初始化的对象时,但在你使用它之前,该对象已经消失了? - bobobobo
@bobobobo:如果你遵循内存管理规则,就不会出现这种情况。autorelease的行为是非常可预测的——对象会一直存在,直到当前的自动释放池被清空,而这只会在当前事件循环结束时发生(除非你故意提前清空)。举个例子,如果你将一个实例变量指向该对象但没有对其进行保留操作,然后在很久之后尝试访问它,那么在你有机会使用它之前,该对象已经消失了——但这是因为你在没有保留对象时违反了内存管理协议。 - Chuck

3

以下是苹果内存管理文档中提供的示例:

– (id)findMatchingObject:(id)anObject 
{ 
    id match = nil; 
    while (match == nil) { 
        NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; 
        /* Do a search that creates a lot of temporary objects. */ 
        match = [self expensiveSearchForObject:anObject]; 
        if (match != nil) { 
            [match retain]; /* Keep match around. */ 
        } 
        [subPool release]; 
    } 
    return [match autorelease];   /* Let match go and return it. */ 
}

2

是的,这是最好的方法。自动释放只适用于您知道的代码交互。一旦您存储了一个对象,您应该知道持有引用的对象不会在您使用完对象之前死亡/超出范围,或者您需要保留对象。


1

只有自动释放的对象才能保证在方法结束后被释放。毕竟,调用您方法的方法可能已经创建了自己的池并在您方法之后立即释放它。


严格来说,这也不能保证,因为您可以在一个方法中创建一个池,自动释放一些对象,并在另一个方法中清空该池。这是一个可疑的设计,但是有效的:这些对象将持续存在于池的创建到池的清空之间,无论创建池的方法何时返回。 - Peter Hosey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接