【问题标题】:When does autorelease actually cause a release in Cocoa Touch?autorelease 什么时候真正导致 Cocoa Touch 中的释放?
【发布时间】:2010-10-14 23:23:25
【问题描述】:

我知道您需要小心使用 iOS 上的 autorelease。我有一个方法返回调用者需要的对象allocs,所以在这种情况下——据我所知——我需要在返回之前将autorelease发送到被调用者中的对象。

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

我已求助于从调用者发送retain 消息,这样对象就不会被释放,然后在dealloc 中显式释放它。

这是最好的方法吗?

【问题讨论】:

    标签: cocoa-touch memory-management autorelease nsautoreleasepool


    【解决方案1】:

    是的,这是最好的方法。自动释放实际上只适用于您知道的代码中的交互。一旦你存储了一个对象,你要么知道持有引用的对象不会死/超出范围,直到你也完成了该对象,或者你需要保留该对象。

    【讨论】:

      【解决方案2】:

      自动释放池通常在每次运行循环迭代后释放。大致来说,每个 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
      

      您所描述的是预期的行为。如果您想保留一个对象比这更长的时间,您需要明确地保留它。

      【讨论】:

        【解决方案3】:

        仅保证自动释放的对象将在您的方法结束后释放。毕竟,调用您的方法的方法可以创建自己的池并在您的方法之后立即释放它。

        【讨论】:

        • 严格来说,即使这样也不能保证,因为您可以在一种方法中创建一个池,自动释放一些对象,并在另一种方法中耗尽池。一个可疑的设计,但有效:无论创建池返回的方法如何,对象都会从池的创建到池的排水一直持续存在。
        【解决方案4】:

        使用autorelease 是一种表达方式,“对象,我不再想要你了,但我会把你交给可能想要你的人,所以现在不要消失。”因此,该对象将停留足够长的时间,以便您从方法中返回它或将其提供给另一个对象。当某些代码想要保留对象时,它必须通过retaining 来声明所有权。

        请参阅 the memory management guidelines,了解正确使用 autorelease 所需的所有信息。

        【讨论】:

        • 很好的答案但是这样安全吗?有没有这样一个例子,当您返回一个您 [[[object alloc] init] autorelease] 的对象时,该对象在您有机会使用它之前就消失了?
        • @bobobobo:如果您遵循内存管理规则,则不会。 autorelease 的行为是完全可以预测的——对象将一直存在,直到当前自动释放池被耗尽,直到当前事件循环结束时才会发生(除非你故意让它更快发生)。例如,如果您将一个实例变量指向该对象,但不保留它,然后稍后再尝试访问它,那么该对象将在您有机会使用它之前就消失了——但那是因为您破坏了内存管理当您没有保留该对象时签订合同。
        【解决方案5】:

        这是the Apple Memory Management document中提供的示例:

        – (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. */ 
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-09
          相关资源
          最近更新 更多