NSOperationQueue
miliki waitUntilAllOperationsAreFinished
, tetapi saya tidak ingin menunggu secara bersamaan. Saya hanya ingin menyembunyikan indikator kemajuan di UI saat antrian selesai.
Apa cara terbaik untuk mencapai ini?
Saya tidak bisa mengirim notifikasi dari NSOperation
s saya , karena saya tidak tahu mana yang akan terakhir, dan [queue operations]
mungkin belum kosong (atau lebih buruk - terisi kembali) ketika notifikasi diterima.
Jawaban:
Gunakan KVO untuk mengamati
operations
properti antrian Anda, lalu Anda dapat mengetahui apakah antrian Anda telah selesai dengan memeriksa[queue.operations count] == 0
.Di suatu tempat di file tempat Anda melakukan KVO, nyatakan konteks untuk KVO seperti ini ( info selengkapnya ):
Saat Anda mengatur antrian Anda, lakukan ini:
Kemudian lakukan ini di
observeValueForKeyPath
:(Ini mengasumsikan bahwa Anda
NSOperationQueue
ada di properti bernamaqueue
)Di beberapa titik sebelum objek Anda sepenuhnya deallocs (atau ketika berhenti peduli tentang status antrian), Anda harus membatalkan pendaftaran dari KVO seperti ini:
Tambahan: iOS 4.0 memiliki
NSOperationQueue.operationCount
properti, yang menurut dokumen sesuai dengan KVO. Namun, jawaban ini masih akan berfungsi di iOS 4.0, jadi masih berguna untuk kompatibilitas ke belakang.sumber
operationCount
samaNSOperationQueue
berpotensi menyebabkan bug, dalam hal ini Anda perlu menggunakan argumen konteks dengan benar. Ini tidak mungkin terjadi, tapi pasti mungkin. (Mengeja masalah sebenarnya lebih membantu daripada menambahkan snark + tautan)Jika Anda mengharapkan (atau menginginkan) sesuatu yang cocok dengan perilaku ini:
Anda harus menyadari bahwa jika sejumlah operasi "pendek" sedang ditambahkan ke antrian Anda mungkin melihat perilaku ini sebagai gantinya (karena operasi dimulai sebagai bagian dari penambahan ke antrian):
Dalam proyek saya, saya perlu mengetahui kapan operasi terakhir selesai, setelah sejumlah besar operasi telah ditambahkan ke serial NSOperationQueue (yaitu, maxConcurrentOperationCount = 1) dan hanya ketika semuanya telah selesai.
Googling Saya menemukan pernyataan ini dari pengembang Apple sebagai tanggapan atas pertanyaan "apakah serial NSoperationQueue FIFO?" -
Dalam kasus saya, dimungkinkan untuk mengetahui kapan operasi terakhir ditambahkan ke antrian. Jadi setelah operasi terakhir ditambahkan, saya menambahkan operasi lain ke antrian, dengan prioritas lebih rendah, yang tidak melakukan apa-apa selain mengirim pemberitahuan bahwa antrian telah dikosongkan. Berdasarkan pernyataan Apple, ini memastikan bahwa hanya satu pemberitahuan yang dikirim hanya setelah semua operasi selesai.
Jika operasi ditambahkan dengan cara yang tidak memungkinkan untuk mendeteksi yang terakhir, (yaitu, non-deterministik) maka saya pikir Anda harus menggunakan pendekatan KVO yang disebutkan di atas, dengan logika penjaga tambahan ditambahkan untuk mencoba mendeteksi jika lebih jauh operasi dapat ditambahkan.
:)
sumber
Bagaimana jika menambahkan NSOperation yang bergantung pada semua yang lain sehingga akan berjalan terakhir?
sumber
Salah satu alternatifnya adalah dengan menggunakan GCD. Lihat ini sebagai referensi.
sumber
Beginilah cara saya melakukannya.
Siapkan antrian, dan daftarkan untuk perubahan di properti operasi:
... dan pengamat (dalam hal ini
self
) mengimplementasikan:Dalam contoh ini "pemintal" adalah
UIActivityIndicatorView
pertunjukan bahwa sesuatu sedang terjadi. Jelas Anda dapat berganti untuk menyesuaikan ...sumber
for
lingkaran tampaknya berpotensi mahal (apa jika Anda membatalkan semua operasi sekaligus Alangkah tidak mendapatkan kinerja kuadrat ketika antrian sedang dibersihkan??)Saya menggunakan kategori untuk melakukan ini.
NSOperationQueue + Penyelesaian. H
NSOperationQueue + Penyelesaian.m
Penggunaan :
Sumber: https://gist.github.com/artemstepanenko/7620471
sumber
waitUntilFinished
seharusnyaYES
Mulai iOS 13.0 , properti operationCount dan operasi tidak digunakan lagi. Sangat mudah untuk melacak sendiri jumlah operasi dalam antrean Anda dan mengaktifkan Notifikasi ketika semuanya telah selesai. Contoh ini juga bekerja dengan subclass Asynchronous dari Operation .
Di bawah ini adalah subkelas Operasi untuk pengoperasian asinkron yang mudah
}
sumber
decrementOperationCount()
metode dipanggil?Bagaimana dengan menggunakan KVO untuk mengamati
operationCount
properti antrian? Kemudian Anda akan mendengarnya saat antrean kosong, dan juga saat antrean sudah tidak lagi kosong. Berurusan dengan indikator kemajuan mungkin sesederhana melakukan sesuatu seperti:sumber
NSOperationQueue
dari 3.1 mengeluh bahwa itu tidak sesuai dengan KVO untuk kuncinyaoperationCount
.operationCount
properti tersebut sudah ada.Tambahkan operasi terakhir seperti:
Begitu:
sumber
Dengan ReactiveObjC saya menemukan ini berfungsi dengan baik:
sumber
FYI, Anda dapat mencapai ini dengan dispatch_group GCD dalam 3 cepat . Anda bisa mendapatkan pemberitahuan ketika semua tugas telah selesai.
sumber
Anda dapat membuat yang baru
NSThread
, atau menjalankan selektor di latar belakang, dan menunggu di sana. Jika sudahNSOperationQueue
selesai, Anda bisa mengirimkan notifikasi Anda sendiri.Saya sedang memikirkan sesuatu seperti:
sumber
Jika Anda menggunakan Operation ini sebagai kelas dasar Anda, Anda bisa meneruskan
whenEmpty {}
blok ke OperationQueue :sumber
Tanpa KVO
sumber
Jika Anda sampai di sini mencari solusi dengan menggabungkan - saya akhirnya hanya mendengarkan objek negara saya sendiri.
sumber