我已阅读Concurrency Programming Guide
在指南中,文本声明GCD调度队列定义了他们自己的@autoreleasepool池,并提到仍然建议在每个调度级别定义一个,但是对于NSOperation没有说什么,Apple提供的示例代码也没有显示@autoreleasepool结构的用法。在NSOperation的背景下,模糊地提到@autoreleasepool的唯一地方是修订历史,
2012-07-17 - 删除了有关使用操作的自动释放池使用情况的过时信息。
查看在线提供的示例代码,例如http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues在基于NSOperations的对象的实现中使用@autoreleasepool,例如:
@implementation ImageDownloader
- (void)main {
@autoreleasepool {
...
}
}
@end
答案 0 :(得分:35)
如果您派生自NSOperation
并实施main
方法,则无需设置自动释放池。 start
方法的默认实现会推送NSAutoReleasePool
,调用main
,然后弹出NSAutoReleasePool
。 NSInvocationOperation
和NSBlockOperation
也是如此,它们共享start
方法的相同实现。
以下是对start
的{{1}}方法的简略反汇编。注意调用NSPushAutoreleasePool,然后调用main,然后调用NSPopAutoreleasePool:
NSOperation
以下是运行
的一些示例代码的快照Foundation`-[newMyObj__NSOperationInternal _start:]:
0x7fff8e5df30f: pushq %rbp
...
0x7fff8e5df49c: callq *-0x16b95bb2(%rip) ; (void *)0x00007fff8d9d30c0: objc_msgSend
0x7fff8e5df4a2: movl $0x1, %edi
; new NSAutoreleasePool is pushed here
0x7fff8e5df4a7: callq 0x7fff8e5df6d6 ; NSPushAutoreleasePool
... NSOperation main is called
0x7fff8e5df6a4: callq *-0x16b95dba(%rip) ; (void *)0x00007fff8d9d30c0: objc_msgSend
0x7fff8e5df6aa: movq %r15, %rdi
; new NSAutoreleasePool is popped here, which releases any objects added in the main method
0x7fff8e5df6ad: callq 0x7fff8e5e1408 ; NSPopAutoreleasePool
在MyObj
方法中分配,我确保该对象必须自动释放main
返回main
,下图显示当前自动释放池调用_start
的堆栈跟踪,弹出MyObj dealloc
作为参考,这是我用来验证行为的示例代码:
_start
Grand Central Dispatch同样根据Concurrency Programming Guide管理调度队列的自动释放池:
如果您的块创建了多个Objective-C对象,您可能希望将块的代码部分包含在@autorelease块中,以处理这些对象的内存管理。尽管GCD调度队列具有自己的自动释放池,但它们无法保证这些池何时耗尽。如果您的应用程序受内存限制,则创建自己的自动释放池可以让您以更加固定的时间间隔释放自动释放对象的内存。