在ARC(自动引用计数)的大多数情况下,我们根本不需要考虑Objective-C对象的内存管理。不允许再创建NSAutoreleasePools了,但是有一个新的语法:
@autoreleasepool {
…
}
我的问题是,当我不应该手动释放/自动释放时,为什么我还需要这个?
编辑:简单总结一下我从所有的回答和评论中得到的东西:
新语法:
@autoreleasepool{…}是用于
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
…
[pool drain];
更重要的是:
ARC uses autorelease as well as release.
It needs an auto release pool in place to do so.
ARC doesn't create the auto release pool for you. However:
The main thread of every Cocoa app already has an autorelease pool in it.
There are two occasions when you might want to make use of @autoreleasepool:
When you are in a secondary thread and there is no auto release pool, you must make your own to prevent leaks, such as myRunLoop(…) { @autoreleasepool { … } return success; }.
When you wish to create a more local pool, as @mattjgalloway has shown in his answer.
ARC并没有摆脱保留、释放和自动释放,它只是为你添加了所需的。所以仍然有保留的调用,仍然有释放的调用,仍然有自动释放的调用,仍然有自动释放池。
他们对新的Clang 3.0编译器和ARC所做的另一个改变是,他们用@autoreleasepool编译器指令取代了NSAutoReleasePool。NSAutoReleasePool一直是一个特殊的"对象"他们这样做是为了使用它的语法不会与对象混淆所以它通常更简单一点。
所以基本上,你需要@autoreleasepool,因为仍然有自动释放池需要担心。您只是不需要担心添加自动释放调用。
使用自动释放池的示例:
- (void)useALoadOfNumbers {
for (int j = 0; j < 10000; ++j) {
@autoreleasepool {
for (int i = 0; i < 10000; ++i) {
NSNumber *number = [NSNumber numberWithInt:(i+j)];
NSLog(@"number = %p", number);
}
}
}
}
当然,这是一个非常做作的例子,但是如果你在外部for循环中没有@autoreleasepool,那么你将在以后释放100000000个对象,而不是每次释放10000个对象。
更新:
也可以看到这个答案- https://stackoverflow.com/a/7950636/1068248 -为什么@autoreleasepool与ARC无关。
更新:
我研究了一下这里发生的事情,并把它写在了我的博客上。如果你看一下这里,你会清楚地看到ARC在做什么,以及新样式@autoreleasepool以及它如何引入一个作用域,被编译器用来推断哪些保留、释放和自动释放是必要的。
人们经常将ARC误解为某种垃圾收集或类似的东西。事实是,经过一段时间后,苹果公司的人(感谢llvm和clang项目)意识到Objective-C的内存管理(所有的保留和释放等)可以在编译时完全自动化。这是通过阅读代码,甚至在它运行之前!:)
为了这样做,只有一个条件:我们必须遵守规则,否则编译器将无法在编译时自动执行该过程。因此,为了确保我们永远不会违反规则,我们不允许明确地写释放、保留等。这些调用由编译器自动注入到代码中。因此在内部我们仍然拥有自动发行,保留,发行等内容。只是我们不需要再写了。
ARC的A在编译时是自动的,这比垃圾收集等运行时要好得多。
我们仍然有@autoreleasepool{…}因为它不违反任何规则,我们可以在任何需要的时候自由地创建/排泄我们的池:)。
引自https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html:
Autorelease Pool Blocks and Threads
Each thread in a Cocoa application maintains its own stack of
autorelease pool blocks. If you are writing a Foundation-only program
or if you detach a thread, you need to create your own autorelease
pool block.
If your application or thread is long-lived and potentially generates
a lot of autoreleased objects, you should use autorelease pool blocks
(like AppKit and UIKit do on the main thread); otherwise, autoreleased
objects accumulate and your memory footprint grows. If your detached
thread does not make Cocoa calls, you do not need to use an
autorelease pool block.
Note: If you create secondary threads using the POSIX thread APIs
instead of NSThread, you cannot use Cocoa unless Cocoa is in
multithreading mode. Cocoa enters multithreading mode only after
detaching its first NSThread object. To use Cocoa on secondary POSIX
threads, your application must first detach at least one NSThread
object, which can immediately exit. You can test whether Cocoa is in
multithreading mode with the NSThread class method isMultiThreaded.
...
在自动引用计数(ARC)中,系统使用相同的方法
引用计数系统作为MRR,但它插入适当的内存
管理方法在编译时为您调用。你很坚强
鼓励在新项目中使用ARC。如果你使用ARC,就有
通常不需要理解底层实现
在本文档中描述,尽管在某些情况下可能是
有帮助的。有关ARC的更多信息,请参见过渡到ARC发行说明。