ARC是否支持调度队列?


95

我正在阅读有关“调度队列的内存管理”的苹果文档:

即使实现垃圾收集的应用程序,您仍然必须保留并释放您的调度队列和其他调度对象。Grand Central Dispatch不支持垃圾回收模型来回收内存。

我知道ARC不是垃圾收集器,但我想确定我不需要dispatch_retain和dispatch_release我的dispatch_queue_t

Answers:


234

简短的答案:是,ARC保留并释放调度队列。







现在长答案...

如果您的部署目标低于iOS 6.0或Mac OS X 10.8

您需要在队列上使用dispatch_retaindispatch_release。ARC不管理它们。

如果您的部署目标是iOS 6.0或Mac OS X 10.8或更高版本

ARC将为您管理队列。您不需要(也不能)使用,dispatch_retain或者dispatch_release是否启用了ARC。

细节

从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.

这意味着你可以把你的队列中的NSArrayNSDictionary,或与一个属性strongweakunsafe_unretainedassign,或retain属性。这也意味着,如果您从某个块中引用队列,该块将自动保留该队列。

因此,如果您的部署目标至少是iOS 6.0或Mac OS X 10.8,并且已启用 ARC,则ARC将保留并释放您的队列,并且编译器将标记任何尝试使用dispatch_retaindispatch_release作为错误。

如果您的部署目标是至少6.0的iOS或Mac OS X 10.8,和你有ARC禁用,您必须手动保留和释放你的队列或者通过调用dispatch_retaindispatch_release通过发送队列retainrelease消息(像[queue retain][queue release])。

为了与旧代码库兼容,可以通过定义OS_OBJECT_USE_OBJC为,防止编译器将队列视为Objective-C对象0。例如,您可以将其放在.pch文件中(在任何#import语句之前):

#define OS_OBJECT_USE_OBJC 0

或者您可以OS_OBJECT_USE_OBJC=0在构建设置中添加为预处理器宏。如果设置OS_OBJECT_USE_OBJC0,ARC将不会为您保留或释放您的队列,您必须使用dispatch_retain和自己进行dispatch_release


1
但是请注意,新更改将调度对象指定为Objective-C对象。因此,即使禁用了ARC,这些对象如果被块捕获也将自动保留-就像所有其他Objective-C对象一样。
乔迪·哈金斯

3
有一个有趣的边缘案例。如果库部署到iOS的5.1和您的应用程序6.0,您正在使用ARC,你需要dispatch_release NULL你的5.1的目标dealloc代码。否则,某些东西(由编译器生成的代码?运行时本身?)将尝试第二次释放该对象。
史蒂文·费舍尔

使用Mac OS 10.7时需要分发我创建的其他源对象吗?
p0lAris

您必须在OS X 10.7下手动保留/释放所有GCD对象。
抢马约夫2015年

23

此处只是后续操作...如果最小部署目标是iOS 6,则ARC现在可以对其进行管理。


这也适用于山狮。如果您的部署目标是iOS 6或Mountain Lion,则您(默认情况下)不能使用dispatch_release,因为这是一个宏,该宏将释放消息发送到ARC不允许的对象。
埃米尔·埃里克森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.