什么时候我应该将我的代码包装到自动释放池中

时间:2012-05-13 16:36:33

标签: iphone objective-c memory-management autorelease

我是objective-c的新手,我知道基本的内存管理规则,例如何时retain release autorelease。但我不知道何时将代码包装到自动释放池中以及为什么?

4 个答案:

答案 0 :(得分:22)

与其他性能优化一样,如果您发现内存使用率很高,通常只应向代码中添加额外的自动释放池(例如,使用Instruments)会引导您将其他自动释放池作为解决方案。

也就是说,您可以在自动释放池中的紧密循环中包装创建大量临时对象的代码。默认自动释放池在运行循环周期结束时耗尽。因此,如果您在代码中的for循环的每次迭代中创建了大量临时对象,则默认自动释放池将在整个循环运行之后才会耗尽,这意味着您创建的所有临时对象都可以累加到高临时内存使用率(有时称为“高水位线”)。您可以将循环的每个迭代包装在@autoreleasepool中,以使得在该循环迭代中创建的不需要的,自动释放的临时对象更快地被释放。

答案 1 :(得分:12)

扩展先前的答案:

自动发布池用于自动向添加到其中的对象发送release消息。

在iOS或Cocoa程序中,自动发布池会在主线程上自动创建,并在运行循环结束时耗尽。

也就是说,在另一个线程上使用自动释放的对象时,必须使用自动释放池。

因此,如果将线程分离到某个方法,则将线程代码包装在自动释放池中。 否则,线程中创建的自动释放对象将泄漏。

自动释放池的另一个用途是优化使用大量内存的代码部分,因此它们在运行循环结束之前被释放。

但它只涉及自动发布的对象。

例如:

- ( void )test
{
    NSMutableArray * a = [ [ NSMutableArray alloc ] init ];

    [ a release ];
}

此处不需要自动释放池,因为您没有自动释放的对象 <{1}}变量将立即释放,因为它已被明确分配并释放。

现在这个:

a

这里您使用的是便利构造函数,这意味着您没有该对象的所有权 这也意味着该对象已添加到当前的自动释放池中(如果有的话)。

因此,当此自动释放池耗尽时,它将被释放,因此可能需要一些周期......

如果您编写的代码部分使用大量内存,则可以使用另一个自动释放池,以便在方法返回时释放自动释放的对象:

- ( void )test
{
    NSMutableArray * a = [ NSMutableArray arrayWithCapacity ];
}

答案 2 :(得分:1)

所有自动释放的对象在技术上都放在自动释放池中。通常在主函数内部创建一个默认值。至于在非默认自动释放池中包装对象,通常将其作为优化来完成。

通常不需要使用显式自动释放池,因为默认的自动释放池会在应用程序的运行循环中自动排出。但是,如果您的应用程序在从事件处理程序返回之前创建了许多自动释放的对象,则它可以为这些对象使用大量内存。因此,如果将代码包装在显式自动释放池中,则自动释放的对象将放在那里而不是默认池中。这允许您定期清空此池以防止自动释放的对象累积。

答案 3 :(得分:0)

但是,有三种情况可能会使用您自己的自动释放池块:

  1. 如果您正在编写一个不基于UI框架的程序,例如命令行工具。

  2. 如果编写一个创建许多临时对象的循环。您可以在循环内使用自动释放池块在下一次迭代之前处理这些对象。在循环中使用自动释放池块有助于减少应用程序的最大内存占用量。

  3. 如果你产生了一个辅助线程。