【问题标题】:Does ARC support dispatch queues?ARC 是否支持调度队列?
【发布时间】:2012-01-26 23:10:31
【问题描述】:

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

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

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

【问题讨论】:

    标签: objective-c automatic-ref-counting grand-central-dispatch


    【解决方案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.1 dealloc 代码中 dispatch_release 和 NULL 对象。否则,某些东西(编译器生成的代码?运行时本身?)会再次尝试释放对象。
    • 在使用 Mac OS 10.7 时是否需要调度我创建的其他源对象?
    • 您必须在 OS X 10.7 下手动保留/释放所有 GCD 对象。
    【解决方案2】:

    这里只是跟进...如果您的最低部署目标是 iOS 6,ARC 现在可以管理它们。

    【讨论】:

    • 这也适用于山狮。如果您的部署目标是 iOS 6 或 Mountain Lion,则不能(默认)使用 dispatch_release,因为这是一个宏,它会向对象发送发布消息,而 ARC 不允许这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2012-03-25
    • 2012-11-11
    相关资源
    最近更新 更多