Apakah ARC mendukung antrian pengiriman?

95

Saya membaca dokumentasi apple tentang "Memory Management for Dispatch Queues":

Meskipun Anda menerapkan aplikasi pengumpulan sampah, Anda masih harus mempertahankan dan melepaskan antrean pengiriman dan objek pengiriman lainnya. Grand Central Dispatch tidak mendukung model pengumpulan sampah untuk mendapatkan kembali memori.

Saya tahu bahwa ARC bukanlah pengumpul sampah tetapi saya ingin memastikan bahwa saya tidak perlu dispatch_retain dan dispatch_release dispatch_queue_t saya

flagg19
sumber

Jawaban:

234

Jawaban singkatnya: YA, ARC mempertahankan dan melepaskan antrian pengiriman.







Dan sekarang untuk jawaban yang panjang…

Jika target penerapan Anda lebih rendah dari iOS 6.0 atau Mac OS X 10.8

Anda perlu menggunakan dispatch_retaindan dispatch_releasedalam antrian Anda. ARC tidak mengelolanya.

Jika target penerapan Anda adalah iOS 6.0 atau Mac OS X 10.8 atau yang lebih baru

ARC akan mengatur antrian Anda untuk Anda. Anda tidak perlu (dan tidak dapat) menggunakan dispatch_retainatau dispatch_releasejika ARC diaktifkan.

Detail

Mulai dari SDK iOS 6.0 dan SDK Mac OS X 10.8, setiap objek pengiriman (termasuk a dispatch_queue_t) juga merupakan objek Objective-C. Ini didokumentasikan di <os/object.h>file header:

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

Ini berarti Anda dapat menyimpan antrian Anda dalam NSArrayatau NSDictionary, atau dalam properti dengan salah satu strong, weak, unsafe_unretained, assign, atau retainatribut. Ini juga berarti bahwa jika Anda merujuk ke antrian Anda dari sebuah blok, blok tersebut akan mempertahankan antrian secara otomatis.

Jadi jika target penerapan Anda setidaknya iOS 6.0 atau Mac OS X 10.8, dan Anda telah mengaktifkan ARC, ARC akan mempertahankan dan melepaskan antrean Anda, dan kompiler akan menandai setiap upaya untuk menggunakan dispatch_retainatau dispatch_releasesebagai kesalahan.

Jika target penerapan Anda setidaknya iOS 6.0 atau Mac OS X 10.8, dan ARC Anda dinonaktifkan , Anda harus secara manual mempertahankan dan melepaskan antrean Anda, baik dengan menelepon dispatch_retaindan dispatch_release, atau dengan mengirimkan antrean retaindan releasepesan (seperti [queue retain]dan [queue release]).

Untuk kompatibilitas dengan codebases tua, Anda dapat mencegah compiler dari melihat antrian Anda sebagai objek Objective-C dengan mendefinisikan OS_OBJECT_USE_OBJCuntuk 0. Misalnya, Anda dapat meletakkan ini di .pchfile Anda (sebelum #importpernyataan apa pun ):

#define OS_OBJECT_USE_OBJC 0

atau Anda bisa menambahkan OS_OBJECT_USE_OBJC=0sebagai makro preprocessor di pengaturan build Anda. Jika Anda menyetel OS_OBJECT_USE_OBJCke 0, ARC tidak akan menyimpan atau merilis antrean untuk Anda, dan Anda harus melakukannya sendiri menggunakan dispatch_retaindan dispatch_release.

merampok mayoff
sumber
1
Perhatikan, bagaimanapun, bahwa perubahan baru menunjuk objek pengiriman sebagai objek Objective-C. Jadi, meskipun ARC dinonaktifkan, objek-objek ini secara otomatis akan dipertahankan jika ditangkap oleh blok - seperti objek Objective-C lainnya.
Jody Hagins
3
Ada kasus tepi yang menarik. Jika perpustakaan Anda menerapkan ke iOS 5.1 dan aplikasi Anda ke 6.0 dan Anda menggunakan ARC, Anda perlu dispatch_release dan NULL objek dalam deallockode 5.1 Anda . Jika tidak, sesuatu (kode yang dihasilkan oleh kompilator? Runtime itu sendiri?) Akan mencoba melepaskan objek untuk kedua kalinya.
Steven Fisher
Apakah saya perlu mengirimkan objek sumber lain yang saya buat saat menggunakan Mac OS 10.7?
p0lAris
Anda harus menyimpan / melepaskan semua objek GCD secara manual di bawah OS X 10.7.
merampok mayoff
23

Ikuti saja di sini ... Jika target penerapan minimum Anda adalah iOS 6, ARC sekarang mengelolanya.

kcharwood.dll
sumber
Ini juga berlaku untuk Mountain Lion. Jika target penerapan Anda adalah iOS 6 atau Mountain Lion, Anda tidak dapat (secara default) menggunakan dispatch_release karena itu adalah makro yang mengirimkan pesan rilis ke objek yang tidak diizinkan di bawah ARC.
Emil Eriksson