Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Core Data
Code

iOS 8: Core Data dan Pengambilan Asinkron

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Core Data from Scratch.
iOS 8: Core Data and Batch Updates

Indonesian (Bahasa Indonesia) translation by Yudha Zubair (you can also view the original English article)

Pada artikel sebelumnya tentang iOS 8 dan Core Data, kami membahas pembaruan batch. Pembaruan Batch bukan satu-satunya API baru di kota. Pada iOS 8 dan OS X Yosemite, dimungkinkan untuk mengambil data secara asinkron. Dalam tutorial ini, kita akan melihat lebih dekat bagaimana menerapkan pengambilan asinkron dan dalam situasi apa aplikasi Anda dapat mengambil manfaat dari API baru ini.

1. Masalah

Seperti pembaruan batch, pengambilan asinkron telah ada dalam daftar keinginan banyak pengembang selama beberapa waktu. Mengambil permintaan bisa jadi rumit, membutuhkan waktu yang tidak sepele untuk diselesaikan. Selama waktu itu, permintaan pengambilan memblokir thread yang sedang berjalan dan, sebagai hasilnya, memblokir akses ke konteks objek yang dikelola yang mengeksekusi permintaan pengambilan. Masalahnya sederhana untuk dipahami, tetapi seperti apa solusi Apple.

2. Solusinya

Jawaban Apple untuk masalah ini adalah pengambilan asinkron. Permintaan pengambilan asinkron berjalan di latar belakang. Ini berarti bahwa itu tidak memblokir tugas-tugas lain saat sedang dieksekusi, seperti memperbarui antarmuka pengguna pada thread utama.

Pengambilan asinkron juga menampilkan dua fitur nyaman lainnya, pelaporan kemajuan dan pembatalan. Permintaan pengambilan asinkron dapat dibatalkan kapan saja, misalnya, ketika pengguna memutuskan permintaan pengambilan terlalu lama untuk diselesaikan. Pelaporan kemajuan adalah tambahan yang berguna untuk menunjukkan kepada pengguna kondisi permintaan pengambilan saat ini.

Pengambilan asinkron adalah API yang fleksibel. Tidak hanya memungkinkan untuk membatalkan permintaan pengambilan asinkron, tetapi juga memungkinkan untuk membuat perubahan pada konteks objek yang dikelola saat permintaan pengambilan asinkron dijalankan. Dengan kata lain, pengguna dapat terus menggunakan aplikasi Anda saat aplikasi mengeksekusi permintaan pengambilan asinkron di latar belakang.

3. Bagaimana Cara Kerjanya?

Seperti pembaruan batch, permintaan pengambilan asinkron diserahkan ke konteks objek terkelola sebagai objek NSPersistentStoreRequest, turunan dari kelas NSAsynchronousFetchRequest tepatnya.

Instance NSAsynchronousFetchRequest diinisialisasi dengan objek NSFetchRequest dan blok completion. Blok completion dijalankan ketika permintaan pengambilan asinkron telah menyelesaikan permintaan pengambilannya.

Mari kita kembali ke aplikasi to-do yang kita buat sebelumnya dalam seri ini dan menggantikan implementasi saat ini dari kelas NSFetchedResultsController dengan permintaan pengambilan asinkron.

Langkah 1: Pengaturan Proyek

Unduh atau klon proyek dari GitHub dan buka di Xcode 6. Sebelum kita dapat mulai bekerja dengan kelas NSAsynchronousFetchRequest, kita perlu membuat beberapa perubahan. Kami tidak akan dapat menggunakan kelas NSFetchedResultsController untuk mengelola data tampilan tabel karena kelas NSFetchedResultsController dirancang untuk berjalan di thread utama.

Langkah 2: Memasang Kembali Results Controller yang Diambil

Mulailah dengan memperbarui ekstensi kelas private dari kelas TSPViewController seperti yang ditunjukkan di bawah ini. Kami menghapus properti fetchedResultsController dan membuat properti baru, items, dari tipe NSArray untuk menyimpan item to-do. Ini juga berarti bahwa kelas TSPViewController tidak perlu lagi mematuhi protokol NSFetchedResultsControllerDelegate.

Sebelum kita memperbaiki metode viewDidLoad, saya pertama-tama ingin memperbarui implementasi protokol UITableViewDataSource. Lihatlah perubahan yang saya buat di blok kode berikut.

Kita juga perlu mengubah satu baris kode dalam metode prepForSegue:sender: seperti yang ditunjukkan di bawah ini.

Terakhir tapi bukan yang akhir, hapus implementasi protokol NSFetchedResultsControllerDelegate karena kita tidak lagi membutuhkannya.

Langkah 3: Membuat Permintaan Ambil Asinkron

Seperti yang Anda lihat di bawah, kami membuat permintaan pengambilan asinkron dalam metode viewDidLoad view controller. Mari kita luangkan waktu untuk melihat apa yang terjadi.

Kami mulai dengan membuat dan mengonfigurasi instance NSFetchRequest untuk menginisialisasi permintaan pengambilan asinkron. Permintaan pengambilan inilah yang akan dijalankan permintaan asinkron di latar belakang.

Untuk menginisialisasi instance NSAsynchronousFetchRequest, kami memanggil initWithFetchRequest:completionBlock:, dimasukan di fetchRequest dan blok completion.

Blok completion dipanggil ketika permintaan pengambilan asinkron telah selesai menjalankan permintaan pengambilannya. Blok completion mengambil satu argumen tipe NSAsynchronousFetchResult, yang berisi hasil kueri serta referensi ke permintaan pengambilan asinkron asli.

Di blok completion, kami memanggil processAsynchronousFetchResult:, dimasukan di objek NSAsynchronousFetchResult. Kami akan melihat metode helper ini dalam beberapa saat.

Menjalankan permintaan pengambilan asinkron hampir identik dengan cara kami menjalankan NSBatchUpdateRequest. Kami memanggil executeRequest:error: pada konteks objek terkelola, dimasukan di permintaan pengambilan asinkron dan pointer ke objek NSError.

Perhatikan bahwa kami menjalankan permintaan pengambilan asinkron dengan memanggil performBlock: pada konteks objek terkelola. Meskipun ini tidak sepenuhnya diperlukan karena metode viewDidLoad, di mana kami membuat dan mengeksekusi permintaan pengambilan asinkron, dipanggil pada thread utama, itu kebiasaan yang baik dan praktik terbaik untuk melakukannya.

Meskipun permintaan pengambilan asinkron dijalankan di latar belakang, perhatikan bahwa metode executeRequest:error: segera kembalikan, menyerahkan kami objek NSAsynchronousFetchResult. Setelah permintaan pengambilan asinkron selesai, objek NSAsynchronousFetchResult yang sama diisi dengan hasil permintaan pengambilan.

Akhirnya, kami memeriksa apakah permintaan pengambilan asinkron dijalankan tanpa masalah dengan memeriksa apakah objek NSError sama dengan nil.

Langkah 4: Memproses Hasil Ambil Asinkron

Metode processAsynchronousFetchResult: tidak lebih dari metode helper di mana kami memproses hasil permintaan pengambilan asinkron. Kami menetapkan properti items view controller dengan konten properti finalResult hasil dan memuat kembali tampilan tabel.

Langkah 5: Bangun dan Jalankan

Bangun proyek dan jalankan aplikasi di Simulator iOS. Anda mungkin terkejut melihat aplikasi Anda berhenti ketika mencoba mengeksekusi permintaan pengambilan asinkron. Untungnya, output di konsol memberi tahu kami apa yang salah.

Jika Anda belum membaca artikel tentang Core Data dan konkurensi, Anda mungkin bingung dengan apa yang Anda baca. Ingat bahwa Core Data mendeklarasikan tiga tipe konkurensi, NSConfinementConcurrencyType, NSPrivateQueueConcurrencyType, dan NSMainQueueConcurrencyType. Setiap kali Anda membuat konteks objek terkelola dengan memanggil metode kelas init , tipe konkurensi konteks objek terkelola yang dihasilkan sama dengan NSConfinementConcurrencyType. Ini adalah tipe konkurensi default.

Masalahnya, bagaimanapun, adalah pengambilan asinkron tidak sesuai dengan tipe NSConfinementConcurrencyType. Tanpa terlalu banyak detail, penting untuk mengetahui bahwa permintaan pengambilan asinkron perlu menggabungkan hasil permintaan pengambilannya dengan konteks objek terkelola yang menjalankan permintaan pengambilan asinkron. Perlu mengetahui antrian pengiriman mana yang dapat melakukan ini dan itu sebabnya hanya NSPrivateQueueConcurrencyType dan NSMainQueueConcurrencyType mendukung pengambilan asinkron. Solusinya sangat sederhana.

Langkah 6: Mengkonfigurasi Konteks Objek yang Dikelola

Buka TSPAppDelegate.m dan perbarui metode managedObjectContext seperti yang ditunjukkan di bawah ini.

Satu-satunya perubahan yang kami buat adalah mengganti metode init dengan initWithConcurrencyType:, dengan memasukan NSMainQueueConcurrencyType sebagai argumen. Ini berarti bahwa konteks objek yang dikelola hanya dapat diakses dari thread utama. Ini berfungsi baik selama kita menggunakan metode performBlock: atau performBlockAndWait: untuk mengakses konteks objek yang dikelola.

Jalankan proyek sekali lagi untuk memastikan bahwa perubahan kami memang telah menyelesaikan masalah.

4. Menampilkan Kemajuan

Kelas NSAsynchronousFetchRequest menambahkan dukungan untuk memantau kemajuan permintaan pengambilan dan bahkan dimungkinkan untuk membatalkan permintaan pengambilan asinkron, misalnya, jika pengguna memutuskan bahwa terlalu lama untuk menyelesaikannya.

Kelas NSAsynchronousFetchRequest memanfaatkan kelas NSProgress untuk pelaporan kemajuan serta membatalkan permintaan pengambilan asinkron. Kelas NSProgress, tersedia sejak iOS 7 dan OS X 10.9, adalah cara cerdas untuk memantau kemajuan suatu tugas tanpa harus secara ketat memasangkan tugas ke antarmuka pengguna.

Kelas NSProgress juga mendukung pembatalan, yang merupakan bagaimana permintaan pengambilan asinkron dapat dibatalkan. Mari kita cari tahu apa yang perlu kita lakukan untuk mengimplementasikan pelaporan kemajuan untuk permintaan pengambilan asinkron.

Langkah 1: Menambahkan SVProgressHUD

Kami akan menunjukkan kepada pengguna kemajuan permintaan pengambilan asinkron menggunakan pustaka SVProgressHUD milik Sam Vermette. Unduh perpustakaan dari GitHub dan tambahkan folder SVProgressHUD ke proyek Xcode Anda.

Langkah 2: Menyiapkan NSProgress

Dalam artikel ini, kami tidak akan mengeksplorasi kelas NSProgress secara mendetail, tetapi jangan ragu untuk membaca lebih lanjut tentang hal itu dalam dokumentasi. Kami membuat instance NSProgress di blok yang kami serahkan ke metode performBlock: dalam metode viewDidLoad view controller.

Anda mungkin terkejut bahwa kami menetapkan jumlah unit menjadi 1. Alasannya sederhana. Ketika Core Data mengeksekusi permintaan pengambilan asinkron, ia tidak tahu berapa banyak record yang akan ditemukan di store persisten. Ini juga berarti bahwa kami tidak akan dapat menunjukkan kemajuan relatif kepada pengguna — persentase. Sebagai gantinya, kami akan menunjukkan kepada pengguna kemajuan absolut — jumlah record yang telah ditemukan.

Anda bisa memperbaiki masalah ini dengan melakukan permintaan pengambilan untuk mengambil jumlah record sebelum Anda menjalankan permintaan pengambilan yang asinkron. Saya lebih suka untuk tidak melakukan ini, karena ini juga berarti bahwa mengambil record dari store persisten membutuhkan waktu lebih lama untuk diselesaikan karena permintaan pengambilan ekstra di awal.

Langkah 3: Menambahkan Observer

Saat kami menjalankan permintaan pengambilan asinkron, kami segera menyerahkan objek NSAsynchronousFetchResult. Objek ini memiliki properti progress, yang bertipe NSProgress. Properti progress inilah yang perlu kita amati jika kita ingin menerima pembaruan kemajuan.

Perhatikan bahwa kami memanggil resignCurrent pada objek progress untuk menyeimbangkan yang sebelumnya panggilan becomeCurrentWithPendingUnitCount:. Perlu diingat bahwa kedua metode ini perlu dijalankan pada thread yang sama.

Langkah 4: Menghapus Observer

Di blok completion permintaan pengambilan asinkron, kami menghapus observer dan mengabaikan progres HUD.

Sebelum kita menerapkan observeValueForKeyPath:ofObject:change:context, kita perlu menambahkan pernyataan impor untuk pustaka SVProgressHUD, mendeklarasikan variabel statis ProgressContext yang kita berikan sebagai konteks saat menambahkan dan menghapus pengamat, dan menunjukkan kemajuan HUD sebelum membuat permintaan pengambilan asinkron.

Langkah 5: Pelaporan Kemajuan

Yang tersisa untuk kita lakukan adalah mengimplementasikan metode observeValueForKeyPath:ofObject:change:context:. Kami memeriksa apakah konteksnya sama dengan ProgressContext, membuat objek status dengan mengekstraksi jumlah record  yang diselesaikan dari dictionary change, dan memperbarui progres HUD. Perhatikan bahwa kami memperbarui antarmuka pengguna pada thread utama.

5. Data Dummy

Jika kita ingin menguji aplikasi kita dengan benar, kita membutuhkan lebih banyak data. Meskipun saya tidak merekomendasikan menggunakan pendekatan berikut dalam aplikasi produksi, ini adalah cara cepat dan mudah untuk mengisi database dengan data.

Buka TSPAppDelegate.m dan perbarui metode application:didFinishLaunchingWithOptions seperti yang ditunjukkan di bawah ini. Metode populateDatabase adalah metode helper sederhana di mana kami menambahkan data dummy ke database.

Implementasinya sangat mudah. Karena kami hanya ingin memasukkan data dummy sekaligus, kami memeriksa database default pengguna untuk kunci @"didPopulateDatabase". Jika kunci tidak disetel, kami memasukkan data dummy.

Jumlah record penting. Jika Anda berencana untuk menjalankan aplikasi pada Simulator iOS, maka boleh saja untuk memasukkan 100.000 atau 1.000.000 record. Ini tidak akan berfungsi dengan baik pada perangkat fisik dan akan terlalu lama untuk diselesaikan.

Di dalam for loop, kami membuat objek yang dikelola dan mengisinya dengan data. Perhatikan bahwa kami tidak menyimpan perubahan konteks objek terkelola selama setiap iterasi dari perulangan for.

Terakhir, kami memperbarui database default pengguna untuk memastikan database tidak terisi saat aplikasi diluncurkan berikutnya.

Hebat. Jalankan aplikasi di iOS Simulator untuk melihat hasilnya. Anda akan melihat bahwa dibutuhkan beberapa saat untuk permintaan pengambilan asinkron untuk mulai mengambil record dan memperbarui kemajuan HUD.

6. Melanggar Perubahan

Dengan mengganti kelas results controller yang diambil dengan permintaan pengambilan asinkron, kami telah merusak beberapa bagian aplikasi. Misalnya, mengetuk tanda centang item yang harus dilakukan sepertinya tidak berfungsi lagi. Saat basis data sedang diperbarui, antarmuka pengguna tidak mencerminkan perubahan. Solusinya cukup mudah untuk diperbaiki dan saya akan menyerahkannya kepada Anda untuk mengimplementasikan solusinya. Anda sekarang harus memiliki pengetahuan yang cukup untuk memahami masalah dan menemukan solusi yang sesuai.

Kesimpulan

Saya yakin Anda setuju bahwa pengambilan asinkron secara mengejutkan mudah digunakan. Pengangkatan berat dilakukan oleh Core Data, yang berarti bahwa tidak perlu secara manual menggabungkan hasil permintaan pengambilan asinkron dengan konteks objek yang dikelola. Satu-satunya tugas Anda adalah memperbarui antarmuka pengguna ketika asynchronous mengambil permintaan dari Anda. Bersama dengan pembaruan batch, ini merupakan tambahan yang bagus untuk kerangka kerja Data Core.

Artikel ini juga menyimpulkan seri ini tentang Core Data. Anda telah belajar banyak tentang kerangka kerja Core Data dan Anda tahu semua hal penting untuk menggunakan Core Data dalam aplikasi nyata. Core Data adalah kerangka kerja yang kuat dan, dengan rilis iOS 8, Apple telah menunjukkan kepada kami bahwa itu menjadi lebih baik setiap tahun.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.