首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >需要有关@autoreleasepool的帮助

需要有关@autoreleasepool的帮助
EN

Stack Overflow用户
提问于 2013-08-11 08:35:10
回答 3查看 261关注 0票数 2

高级内存管理编程指南说关于@autoreleasepool:

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

许多程序创建自动释放的临时对象。这些对象会增加程序的内存占用,直到块结束。在许多情况下,允许临时对象累积到当前事件循环迭代的结束并不会导致过多的开销;然而,在某些情况下,您可能会创建大量的临时对象,这些对象大大增加了内存占用,并且希望更快地处理这些对象。在后一种情况下,您可以创建自己的自动释放池块。在块的末尾,临时对象被释放,这通常会导致它们的去分配,从而减少程序的内存占用。 下面的示例演示如何在for循环中使用本地自动释放池块。

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
self.filecontents = nil;
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-08-11 08:39:32

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

代码语言:javascript
运行
复制
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文档中的“保留返回值”和“未保留返回值”。

票数 5
EN

Stack Overflow用户

发布于 2013-08-11 08:40:13

将强属性分配给强属性,然后将其去掉,并将其赋值给强局部变量,并使其超出作用域,两者没有区别。根本的问题是,分配给fileContents的对象被放置在一个自动释放池中,至少在for循环完成所有URL迭代之前,这个池不会被耗尽。将循环体放入@autoreleasepool块中将导致fileContents随每次循环迭代而自动释放。

票数 1
EN

Stack Overflow用户

发布于 2013-08-11 17:31:14

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

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

还有一种过去更受欢迎的模式,如:

代码语言:javascript
运行
复制
NSAutoreleasePool * pool = [NSAutoreleasePool new];
for (int i =0;i>3009;i++){
    //do stuff;
    if(!(i%100))
    {
        [pool drain],pool = [NSAutoreleasePool new];}
}
[pool drain];
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18170163

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档