【问题标题】:Need assistance regarding @autoreleasepool需要有关@autoreleasepool 的帮助
【发布时间】:2013-08-12 18:30:39
【问题描述】:

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

这段代码是否也可以在没有自动释放池的情况下编写并有效管理?

就像创建一个property of fileContents 并在处理后设置它nil

self.filecontents = nil;

【问题讨论】:

  • 这段代码可以在没有 ARP 的情况下编写,因为 ARC 现在在 iOS 中存在。
  • @Ashwin:据我了解,自动释放池独立于手动和自动引用计数。即使使用 MRP,也可以在没有 ARP 的情况下编写代码(只需在下面我建议的答案中将 fileContents = nil 替换为 [fileContents release])。
  • @Ashwin 这完全是错误的。 ARC 引入了autorelease 块格式。除非使用autoreleasepool,否则循环内的自动释放对象将在运行循环到达下一次迭代之前不会被释放(因为UIKitautoreleasepool 块中运行每个事件)。
  • 谢谢! @danielbeard 进行解释,让我更好地理解。

标签: ios objective-c nsautoreleasepool


【解决方案1】:

问题是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

【讨论】:

  • @S.J martin 是对的。另外我更喜欢@autoreleasepool,因为框架代码还在内部使用了很多自动释放的对象(只是假设)。尽管您使用自动释放对象,但使用自动释放也会释放这些对象。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

    猜你喜欢
    • 2015-06-23
    • 2014-12-26
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多