Поддерживает ли ARC очереди отправки?

95

Я читаю документацию Apple по «Управлению памятью для диспетчерских очередей»:

Даже если вы реализуете приложение со сборкой мусора, вы все равно должны сохранять и освобождать очереди отправки и другие объекты отправки. Grand Central Dispatch не поддерживает модель сборки мусора для освобождения памяти.

Я знаю, что ARC не является сборщиком мусора, но я хотел бы быть уверен, что мне не нужно использовать dispatch_retain и dispatch_release мой dispatch_queue_t

флагg19
источник

Ответы:

234

Краткий ответ: ДА, ARC сохраняет и освобождает очереди отправки.







А теперь длинный ответ…

Если ваша цель развертывания ниже iOS 6.0 или Mac OS X 10.8

Вам нужно использовать dispatch_retainи dispatch_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, каждый объект отправки (включая a 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]).

Для совместимости со старыми кодовыми базами вы можете запретить компилятору видеть вашу очередь как объект Objective-C, указав OS_OBJECT_USE_OBJCдля 0. Например, вы можете поместить это в свой .pchфайл (перед любыми #importоператорами):

#define OS_OBJECT_USE_OBJC 0

или вы можете добавить OS_OBJECT_USE_OBJC=0в качестве макроса препроцессора в настройках сборки. Если вы установите OS_OBJECT_USE_OBJCзначение 0, ARC не будет сохранять или освобождать вашу очередь за вас, и вам придется делать это самостоятельно, используя dispatch_retainи dispatch_release.

Роб Мэйофф
источник
1
Однако обратите внимание, что новое изменение обозначает объекты отправки как объекты Objective-C. Таким образом, даже если ARC отключен, эти объекты будут автоматически сохраняться, если они захвачены блоком - как и все другие объекты Objective-C.
Джоди Хагинс,
3
Есть интересный крайний случай. Если ваша библиотека развертывается в iOS 5.1, а ваше приложение - в 6.0, и вы используете ARC, вам необходимо dispatch_release и NULL объект в deallocкоде 5.1 . В противном случае что-то (код, сгенерированный компилятором? Сама среда выполнения?) Попытается освободить объект во второй раз.
Стивен Фишер
Нужно ли мне отправлять другие исходные объекты, которые я создаю при использовании Mac OS 10.7?
p0lAris
Вы должны вручную сохранить / освободить все объекты GCD под OS X 10.7.
Роб Мэйофф
23

Просто продолжение здесь ... Если ваша минимальная цель развертывания - iOS 6, ARC теперь управляет ими.

Kcharwood
источник
Это также относится к Mountain Lion. Если ваша цель развертывания - iOS 6 или Mountain Lion, вы не можете (по умолчанию) использовать dispatch_release, поскольку это макрос, который отправляет сообщение о выпуске объекту, что не разрешено в ARC.
Эмиль Эрикссон,