41
votes

I maintain a dispatch queue as a property with my view controller. I create this queue once in my view controller's init method, and reuse a few times for some background tasks. Before ARC, I was doing this:

@property (nonatomic, assign) dispatch_queue_t filterMainQueue;

And in init:

if (filterMainQueue == nil) {
     filterMainQueue = dispatch_queue_create("com.myQueue.CJFilterMainQueue", NULL);
}

But after ARC, I'm not sure if this should still be "assign", or should it be "strong" or "weak". The ARC convertor script didn't change anything but I'm not sure if a subtle bug is coming from the fact that this queue might be deallocated while it's being used?

What would be the difference between the 3 types of properties, and what will work the best for a dispatch queue, when using ARC?

5

5 Answers

62
votes

Updated answer:

In current OS X and iOS, Dispatch objects are now treated as Obj-C objects by ARC. They will be memory-managed the same way that Obj-C objects will, and you should use strong for your property.

This is controlled by the OS_OBJECT_USE_OBJC macro, defined in <os/object.h>. It's set to 1 by default when your deployment target is OS X 10.8 or higher, or iOS 6.0 or higher. If you're deploying to an older OS, then this is left at 0 and you should see my original answer below.


Original answer:

Dispatch objects (including queues) are not Obj-C objects, so the only possible choice is assign. The compiler will throw an error if you try to use strong or weak. ARC has no impact on GCD.

9
votes

Here is how one would define dispatch_queue_t property for iOS 6.0 and above AND below iOS 6.0

#if OS_OBJECT_HAVE_OBJC_SUPPORT == 1
@property (nonatomic, strong) dispatch_queue_t serialDispatchQueue;
#else
@property (nonatomic, assign) dispatch_queue_t serialDispatchQueue;
#endif

Basically OS_OBJECT_HAVE_OBJC_SUPPORT is defined as 1 for iOS 6.0 and above. (MAC 10.8 and above). Below iOS 6 it is defined as 0.

OS_OBJECT_HAVE_OBJC_SUPPORT defines that OS objects like GCD have objective C support. So ARC, memory management, reference counting etc. applies to GCD objects.

5
votes

Here is what I use:

@property (readwrite, strong, nonatomic) __attribute__((NSObject)) dispatch_queue_t queue;
4
votes

Based on iOS7, I tested whether dispatch_queue object is an objective-C object and I figured out they already are objective-c object. to paraphrase this, attribute((NSObject)) is not necessary now.

1
votes

TL;DR: dispatch_queue_t is an Objective C object now and can be managed with ARC.

I haven't tested how far back this is true, but using the iOS 7 SDK and Xcode 5, dispatch_queue_t is an object type. I am declaring a property for a queue as

@property (nonatomic, strong) dispatch_queue_t syncQueue;

The compiler is happy and everything works as expected. I know definitively that this used to not work in iOS 4 or 5 (pre-ARC it was retain instead of strong). I dug into the definition for dispatch_queue_t and found this:

/*!
 * @typedef dispatch_queue_t
 *
 * @abstract
 * Dispatch queues invoke blocks submitted to them serially in FIFO order. A
 * queue will only invoke one block at a time, but independent queues may each
 * invoke their blocks concurrently with respect to each other.
 *
 * @discussion
 * Dispatch queues are lightweight objects to which blocks may be submitted.
 * The system manages a pool of threads which process dispatch queues and
 * invoke blocks submitted to them.
 *
 * Conceptually a dispatch queue may have its own thread of execution, and
 * interaction between queues is highly asynchronous.
 *
 * Dispatch queues are reference counted via calls to dispatch_retain() and
 * dispatch_release(). Pending blocks submitted to a queue also hold a
 * reference to the queue until they have finished. Once all references to a
 * queue have been released, the queue will be deallocated by the system.
 */
DISPATCH_DECL(dispatch_queue);

By the sounds of that, it shouldn't work, so I checked the definition of DISPATCH_DECL and found this, which explains everything:

/*
 * By default, dispatch 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.
 * See <os/object.h> for details.
 */