2

高级内存管理编程指南关于@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;
4

3 回答 3

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返回一个自动释放的对象。特别是在发布模式下,ARC 编译器删除了许多不必要的保留/自动释放/释放操作。)

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

有关详细信息,请参阅Clang ARC 文档中的“保留的返回值”和“未保留的返回值” 。

于 2013-08-11T08:39:32.693 回答
1

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

于 2013-08-11T08:40:13.870 回答
0

从表面上看似乎是这样,但是您进行的任何可可方法调用都可能在幕后创建一个自动释放的对象……正如您所见,您是否在没有自动释放池的另一个线程上执行相同类型的操作。

如果您有长时间运行的循环,添加一个单独的池是明智的。

还有一种过去更流行的模型,例如:

NSAutoreleasePool * pool = [NSAutoreleasePool new];
for (int i =0;i>3009;i++){
    //do stuff;
    if(!(i%100))
    {
        [pool drain],pool = [NSAutoreleasePool new];}
}
[pool drain];
于 2013-08-11T17:31:14.230 回答