需要有关@autoreleasepool的帮助

时间:2013-08-11 08:35:10

标签: ios objective-c nsautoreleasepool

Advanced Memory Management Programming Guide关于@autoreleasepool:

使用本地自动释放池块来减少峰值内存占用

  

许多程序会创建自动释放的临时对象。这些   对象添加到程序的内存占用,直到结束   块。在许多情况下,允许临时对象累积   直到当前事件循环迭代结束才导致   过度开销;但是,在某些情况下,您可以创建一个   大量临时对象大量增加内存   足迹和你想要更快地处置。在这些   在后一种情况下,您可以创建自己的自动释放池块。在   块的结尾,临时对象被释放,这通常是   导致他们的释放,从而减少程序的内存   足迹。

     

以下示例显示了如何使用本地自动释放池   阻止for循环。

NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {

    @autoreleasepool {
        NSError *error;
        NSString *fileContents = [NSString stringWithContentsOfURL:url
                                         encoding:NSUTF8StringEncoding error:&error];
        /* Process the string, creating and autoreleasing more objects. */
    }
}

这段代码也可以在没有autoreleasepool的情况下编写并有效管理吗?

比如创建property of fileContents并在处理后设置nil

self.filecontents = nil;

3 个答案:

答案 0 :(得分:5)

问题是stringWithContentsOfURL可以返回自动释放的对象。但你可以使用 initWithContentsOfURL代替:

NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
    NSError *error;
    NSString *fileContents = [[NSString alloc] initWithContentsOfURL:url
                                     encoding:NSUTF8StringEncoding error:&error];
    /* Process the string ... */
    fileContents = nil;
}

init...方法返回一个(+1)保留对象,而不是一个自动释放的对象 fileContents = nil释放对象并销毁它(如果没有其他的话 强烈引用它)。

当然,只有在“字符串处理代码”不产生时才有用 其他自动释放的对象。 (另外error,如果设置,将是自动释放的 对象。)

(实际上并非“保证”stringWithContentsOfURL返回自动释放 宾语。特别是在Release模式下,ARC编译器删除了许多不必要的东西 保留/自动释放/释放操作。)

我不知道建立本地自动释放池是否是一项昂贵的操作 (我假设不是)。如果您在循环中处理许多对象而您不知道 究竟是否创建了自动释放的对象,这可能是明智的 只使用本地自动释放池并“不关心它”。 使用“仪器”进行分析也可以提供更多见解。

有关详细信息,请参阅“保留的返回值”和“未保留的返回值” 在Clang ARC documentation

答案 1 :(得分:1)

分配一个强大的属性然后将其取出并分配给一个强大的局部变量并使其超出范围没有区别。基本问题是分配给fileContents的对象被放置在自动释放池中,该池至少在for循环完成迭代所有URL之前不会被耗尽。将循环体放在@autoreleasepool块内会导致fileContents在每次循环迭代时自动释放。

答案 2 :(得分:0)

表面看起来似乎是这样,但你调用的任何cocoa方法都可能在幕后创建一个自动释放的对象...你可以看到你是否在没有自动释放池的情况下在另一个线程上执行相同类型的操作。

如果你有长时间的循环,最好添加一个单独的池。

还有一个过去比较受欢迎的模型:

NSAutoreleasePool * pool = [NSAutoreleasePool new];
for (int i =0;i>3009;i++){
    //do stuff;
    if(!(i%100))
    {
        [pool drain],pool = [NSAutoreleasePool new];}
}
[pool drain];