Czy ARC obsługuje kolejki wysyłek?

95

Czytam dokumentację firmy Apple dotyczącą „Zarządzania pamięcią dla kolejek wysyłkowych”:

Nawet jeśli zaimplementujesz aplikację zbierającą elementy bezużyteczne, nadal musisz zachować i zwolnić kolejki wysyłkowe i inne obiekty wysyłania. Grand Central Dispatch nie obsługuje modelu czyszczenia pamięci do odzyskiwania pamięci.

Wiem, że ARC nie jest odśmiecaczem, ale chciałbym mieć pewność, że nie muszę wysyłać_przechowywania i rozsyłać_wysyłki moje dispatch_queue_t

flagg19
źródło

Odpowiedzi:

234

Krótka odpowiedź: TAK, ARC zachowuje i zwalnia kolejki wysyłek.







A teraz długa odpowiedź…

Jeśli cel wdrożenia jest niższy niż iOS 6.0 lub Mac OS X 10.8

Musisz użyć dispatch_retaini dispatch_releasew swojej kolejce. ARC nimi nie zarządza.

Jeśli celem wdrożenia jest system iOS 6.0 lub Mac OS X 10.8 lub nowszy

ARC będzie zarządzać Twoją kolejką za Ciebie. Nie musisz (i nie możesz) używać dispatch_retainlub dispatch_releasejeśli ARC jest włączone.

Detale

Począwszy od iOS 6.0 SDK i Mac OS X 10.8 SDK, każdy obiekt wysyłki (w tym a dispatch_queue_t) jest również obiektem Objective-C. Jest to udokumentowane w <os/object.h>pliku nagłówkowym:

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

W ten sposób można zapisać kolejkę w sposób NSArraylub NSDictionaryczy w nieruchomości z jednym z strong, weak, unsafe_unretained, assign, lub retainatrybutów. Oznacza to również, że jeśli odwołasz się do swojej kolejki z bloku, blok automatycznie zachowa kolejkę.

Jeśli więc celem wdrożenia jest co najmniej iOS 6.0 lub Mac OS X 10.8 i masz włączone ARC, ARC zachowa i zwolni twoją kolejkę, a kompilator oznaczy każdą próbę użycia dispatch_retainlub dispatch_releasejako błąd.

Jeśli twoim celem jest wdrożenie co najmniej iOS 6.0 lub Mac OS X 10.8 i masz ARC wyłączona , należy ręcznie zachować i uwolnić swoją kolejkę, albo przez wywołanie dispatch_retaini dispatch_release, lub poprzez wysłanie do kolejki retaini releasewiadomości (jak [queue retain]i [queue release]).

Aby zapewnić zgodność ze starymi bazami kodu, możesz uniemożliwić kompilatorowi wyświetlanie kolejki jako obiektu Objective-C, definiując OS_OBJECT_USE_OBJCto 0. Na przykład możesz umieścić to w swoim .pchpliku (przed jakimikolwiek #importinstrukcjami):

#define OS_OBJECT_USE_OBJC 0

lub możesz dodać OS_OBJECT_USE_OBJC=0jako makro preprocesora w ustawieniach kompilacji. Jeśli ustawisz OS_OBJECT_USE_OBJCna 0, ARC nie zatrzyma ani nie zwolni Twojej kolejki za Ciebie i będziesz musiał to zrobić samodzielnie za pomocą dispatch_retaini dispatch_release.

rob mayoff
źródło
1
Należy jednak pamiętać, że nowa zmiana wyznacza obiekty wysyłkowe jako obiekty Objective-C. Tak więc, nawet jeśli ARC jest wyłączone, obiekty te zostaną automatycznie zachowane, jeśli zostaną przechwycone przez blok - tak jak wszystkie inne obiekty Objective-C.
Jody Hagins
3
Jest ciekawy skrajny przypadek. Jeśli Twoja biblioteka jest wdrażana w systemie iOS 5.1, a aplikacja w wersji 6.0 i używasz ARC, musisz dispatch_release i NULL obiekt w deallockodzie 5.1 . W przeciwnym razie coś (kod wygenerowany przez kompilator? Samo środowisko wykonawcze?) Spróbuje zwolnić obiekt po raz drugi.
Steven Fisher
Czy muszę wysyłać inne obiekty źródłowe, które utworzę w systemie Mac OS 10.7?
p0lAris
Musisz ręcznie zachować / zwolnić wszystkie obiekty GCD w systemie OS X 10.7.
rob mayoff
23

Po prostu kontynuacja tutaj ... Jeśli minimalnym celem wdrożenia jest iOS 6, ARC teraz nimi zarządza.

kcharwood
źródło
Dotyczy to również Mountain Lion. Jeśli celem wdrożenia jest iOS 6 lub Mountain Lion, nie możesz (domyślnie) użyć dispatch_release, ponieważ jest to makro, które wysyła komunikat o wersji do obiektu, który nie jest dozwolony w ARC.
Emil Eriksson,