ARC 是不是支持调度队列?
Posted
技术标签:
【中文标题】ARC 是不是支持调度队列?【英文标题】:Does ARC support dispatch queues?ARC 是否支持调度队列? 【发布时间】:2012-01-26 23:10:31 【问题描述】:我正在阅读苹果关于“调度队列的内存管理”的文档:
即使您实现了一个垃圾收集应用程序,您仍然必须保留和释放您的调度队列和其他调度对象。 Grand Central Dispatch 不支持用于回收内存的垃圾收集模型。
我知道 ARC 不是垃圾收集器,但我想确定我不需要 dispatch_retain 和 dispatch_release 我的 dispatch_queue_t
【问题讨论】:
【参考方案1】:简短的回答:是的,ARC 保留和释放调度队列。
现在是长答案……
如果您的部署目标低于 ios 6.0 或 Mac OS X 10.8
您需要在队列中使用dispatch_retain
和dispatch_release
。 ARC 不管理它们。
如果您的部署目标是 iOS 6.0 或 Mac OS X 10.8 或更高版本
ARC 将为您管理您的队列。如果启用了 ARC,则不需要(也不能)使用 dispatch_retain
或 dispatch_release
。
详情
从 iOS 6.0 SDK 和 Mac OS X 10.8 SDK 开始,每个调度对象(包括 dispatch_queue_t
)也是一个 Objective-C 对象。这记录在 <os/object.h>
头文件中:
* By default, libSystem objects such as GCD and XPC objects are declared as
* Objective-C types when building with an Objective-C compiler. This allows
* them to participate in ARC, in RR management by the Blocks runtime and in
* leaks checking by the static analyzer, and enables them to be added to Cocoa
* collections.
*
* NOTE: this requires explicit cancellation of dispatch sources and xpc
* connections whose handler blocks capture the source/connection object,
* resp. ensuring that such captures do not form retain cycles (e.g. by
* declaring the source as __weak).
*
* To opt-out of this default behavior, add -DOS_OBJECT_USE_OBJC=0 to your
* compiler flags.
*
* This mode requires a platform with the modern Objective-C runtime, the
* Objective-C GC compiler option to be disabled, and at least a Mac OS X 10.8
* or iOS 6.0 deployment target.
这意味着您可以将队列存储在NSArray
或NSDictionary
中,或者存储在具有strong
、weak
、unsafe_unretained
、assign
或retain
属性之一的属性中。这也意味着如果你从一个块中引用你的队列,该块将自动保留队列。
所以如果您的部署目标至少是 iOS 6.0 或 Mac OS X 10.8,并且您启用了 ARC,ARC 将保留和释放您的队列,并且编译器会将任何使用dispatch_retain
或dispatch_release
的尝试标记为错误。
如果您的部署目标至少是 iOS 6.0 或 Mac OS X 10.8,并且您已禁用 ARC,您必须手动保留和释放您的队列,要么调用dispatch_retain
和dispatch_release
,或通过发送队列retain
和release
消息(如[queue retain]
和[queue release]
)。
为了与旧代码库兼容,您可以通过将OS_OBJECT_USE_OBJC
定义为0
来防止编译器将您的队列视为Objective-C 对象。例如,您可以将其放在您的 .pch
文件中(在任何 #import
语句之前):
#define OS_OBJECT_USE_OBJC 0
或者您可以在构建设置中添加OS_OBJECT_USE_OBJC=0
作为预处理器宏。如果您将OS_OBJECT_USE_OBJC
设置为0
,ARC 将不会为您保留或释放您的队列,您必须自己使用dispatch_retain
和dispatch_release
来完成。
【讨论】:
但是请注意,新的更改将调度对象指定为 Objective-C 对象。因此,即使 ARC 被禁用,如果被块捕获,这些对象也会自动保留——就像所有其他 Objective-C 对象一样。 有一个有趣的边缘案例。如果您的库部署到 iOS 5.1 并且您的应用程序部署到 6.0 并且您正在使用 ARC,您需要在 5.1dealloc
代码中 dispatch_release
和 NULL
对象。否则,某些东西(编译器生成的代码?运行时本身?)会再次尝试释放对象。
在使用 Mac OS 10.7 时是否需要调度我创建的其他源对象?
您必须在 OS X 10.7 下手动保留/释放所有 GCD 对象。【参考方案2】:
这里只是跟进...如果您的最低部署目标是 iOS 6,ARC 现在可以管理它们。
【讨论】:
这也适用于山狮。如果您的部署目标是 iOS 6 或 Mountain Lion,则不能(默认)使用 dispatch_release,因为这是一个宏,它会向对象发送发布消息,而 ARC 不允许这样做。以上是关于ARC 是不是支持调度队列?的主要内容,如果未能解决你的问题,请参考以下文章