高级内存管理编程指南说关于@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;发布于 2013-08-11 08:39:32
问题是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-11 08:40:13
将强属性分配给强属性,然后将其去掉,并将其赋值给强局部变量,并使其超出作用域,两者没有区别。根本的问题是,分配给fileContents的对象被放置在一个自动释放池中,至少在for循环完成所有URL迭代之前,这个池不会被耗尽。将循环体放入@autoreleasepool块中将导致fileContents随每次循环迭代而自动释放。
发布于 2013-08-11 17:31:14
表面上似乎是这样,但是任何可可方法调用都可能在幕后创建一个自动释放的对象.如您所见,如果您在没有自动释放池的另一个线程上执行相同类型的操作。
如果您有长时间运行的循环,那么添加一个单独的池是明智的。
还有一种过去更受欢迎的模式,如:
NSAutoreleasePool * pool = [NSAutoreleasePool new];
for (int i =0;i>3009;i++){
//do stuff;
if(!(i%100))
{
[pool drain],pool = [NSAutoreleasePool new];}
}
[pool drain];https://stackoverflow.com/questions/18170163
复制相似问题