dispatch_async和autoreleasepool

时间:2014-05-15 23:08:55

标签: objective-c grand-central-dispatch autorelease

我正在使用dispatch_async,它又调用其他使用dispatch_async的代码,该代码使用for循环来分配至少50-100个对象。我怎么知道何时应该使用@autoreleasepool?我可以在分配超过10个对象的任何dispatch_async中使用@autoreleasepool,还是存在使用太多autoreleasepool的风险?

2 个答案:

答案 0 :(得分:6)

由于高级内存管理编程指南Using Autorelease Pools部分建议使用“自动释放池”,“您必须或者这样做是有益的”。我通常不建议只是无缘无故地投入自动释放池,尽管你经常这样做而没有发生任何事故。

除非您正在处理自己的@autoreleasepool个实例(您在此处未执行此操作),或者您正在尝试明确减少因使用而导致的高水位标记,否则不需要NSThread许多自动释放对象。

在确定何时需要自动释放池以降低峰值内存利用率方面,它并不像“我有十个对象”那么简单。这是一个对象大小的问题,现在你有很多。如果处理大图像(例如20000 x 20000像素),则多个图像可能太多。如果处理小对象(字符串,数字等),那么您可以拥有数千个对象而不会导致问题。它仅适用于使用自动释放对象的地方。

所以,我建议采用一种经验方法,你可以考虑(a)常规使用的最高记忆量; (b)您正在使用多少个自动释放对象,并从那里做出决定。

值得注意的是,有一些孤立的情况,必须小心添加自动释放池。典型的示例是,如果存在某些错误,您将为其传回一个对象的方法具有NSError **参数。例如,此代码存在问题:

/** Some method that will optionally return error object.
 *
 *  @param  error  The error object being returned
 *
 *  @return        This returns an NSData if successful, and `nil` upon error.
 *                 See NSError object to determine why it failed.
 */

- (NSData *)someMethod:(NSError * __autoreleasing *)error
{
    @autoreleasepool {

        // do some stuff

        // following line is wrong as the error will be released when pool is drained 

        if (failure)
            *error = [NSError errorWithDomain:kMyAppDomain code:code userInfo:nil];

        // etc
    }
}

在这种情况下,您可以像这样重构它:

- (NSData *)someMethod:(NSError * __autoreleasing *)error
{
    NSError *localError;

    @autoreleasepool {

        // do some stuff

        // save it in some local variable outside of the scope of this block

        if (failure) {
            localError = [NSError errorWithDomain:kMyAppDomain code:code userInfo:nil];
        }
    }

    // now you can return it safely
    *error = localError;

    // etc
}

答案 1 :(得分:2)

冒着不太完全有帮助的风险......

当Instruments的Allocations模板显示您在特定工作流程中使用内存大大推高应用程序的高水位标记(使用自动释放的对象)时,您应该添加@autoreleasepool

换句话说,避免过早优化。