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

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.


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.


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.