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

Core Data dari Awal: NSFetchedResultsController

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Core Data from Scratch.
Core Data from Scratch: Relationships and More Fetching
Core Data from Scratch: More NSFetchedResultsController

Indonesian (Bahasa Indonesia) translation by Yusuf Samin (you can also view the original English article)

Dalam bagian seri ini sebelumnya, kami membahas dasar-dasar kerangka kerja Data Inti. Sudah saatnya kita menggunakan pengetahuan kita dengan membangun aplikasi sederhana yang ditenagai oleh Core Data.

Dalam tutorial ini, kita juga akan bertemu pemain bintang lain dari kerangka kerja Core Data, kelas NSFetchedResultsController. Aplikasi yang akan kami buat mengelola daftar item yang harus dilakukan. Dengan aplikasi ini, kita dapat menambah, memperbarui, dan menghapus item yang harus dilakukan. Anda akan segera mengetahui bahwa kelas NSFetchedResultsController membuat ini sangat mudah dilakukan.

1. Pengaturan Proyek

Buka Xcode, pilih New > Project ... dari menu File, dan pilih templat Single View Application dari iOS > kategori Application.

Beri nama proyek Done, atur Devices ke iPhone, dan beri tahu Xcode tempat Anda ingin menyimpan proyek.

Karena kami memilih templat Single View Application, Xcode belum membuat pengaturan Core Data untuk kami. Namun, mengatur stack Core Data seharusnya mudah, jika Anda telah membaca bagian seri ini sebelumnya.

2. Pengaturan Core Data

Buka file implementasi dari kelas delegasi aplikasi, TSPAppDelegate.m, dan nyatakan tiga properti dalam ekstensi kelas privat, managedObjectContext, managedObjectModel, dan persistentStoreCoordinator. Jika Anda bingung dengan langkah ini, maka saya sarankan Anda mengunjungi kembali artikel pertama dari seri ini, yang mencakup tumpukan Core Data secara detail.

Perhatikan bahwa saya juga telah menambahkan pernyataan impor untuk kerangka kerja Core Data di bagian atas TSPAppDelegate.m.

Seperti yang mungkin Anda ingat, stack Core Data yang diatur malas. Ini berarti bahwa kita instantiate konteks objek terkelola, model objek terkelola, dan koordinator toko persisten saat mereka dibutuhkan oleh aplikasi. Dengan kata lain, objek yang disebutkan di atas adalah instantiated di getter dari properti terkait. Snippet kode berikut akan terlihat sangat familier.

Ada tiga hal yang harus Anda waspadai. Pertama, model data, yang akan kita buat selanjutnya, akan dinamai Done.momd. Kedua, kita akan menamai backing store Done dan itu akan menjadi database SQLite. Ketiga, jika backing store tidak kompatibel dengan model data, kami memanggil abort, membunuh aplikasi. Seperti yang saya sebutkan sebelumnya dalam seri ini, sementara ini baik-baik saja selama pengembangan, Anda tidak boleh memanggil abort dalam produksi. Kami akan meninjau kembali masalah migrasi dan ketidakcocokan di seri ini nanti.

Meskipun aplikasi kami tidak akan berhenti jika Anda mencoba menjalankannya, stack Core Data tidak akan diatur dengan benar. Alasannya sederhana, kami belum membuat model data. Mari kita selesaikan itu di langkah selanjutnya.

3. Membuat Model Data

Pilih New > File... dari menu File dan pilih Data Model dari iOS > Core Data kategori.

Beri nama file Done, periksa kembali apakah sudah ditambahkan ke target Done, dan beri tahu Xcode tempat menyimpannya.

Model data akan menjadi sangat sederhana. Buat entitas baru dan beri nama TSPItem. Tambahkan tiga atribut ke entitas, name tipe StringcreatedAt tipe Date, dan done dari tipe Boolean.

Tandai atribut yang diperlukan, bukan opsional, dan tetapkan nilai default atribut done menjadi NO.

Stack Core Data diatur dan model data dikonfigurasi dengan benar. Saatnya untuk mengenal kelas baru dari kerangka kerja Core Data, kelas NSFetchedResultsController.

4. Mengelola Data

Artikel ini bukan hanya tentang kelas NSFetchedResultsController, ini tentang apa yang dilakukan kelas NSFetchedResultsController di belakang layar. Biarkan saya mengklarifikasi apa yang saya maksud dengan ini.

Jika kita akan membangun aplikasi kita tanpa kelas NSFetchedResultsController, kita perlu menemukan cara untuk menjaga antarmuka pengguna aplikasi disinkronkan dengan data yang dikelola oleh Core Data. Untungnya, Core Data memiliki solusi elegan untuk masalah ini.

Setiap kali record dimasukkan, diperbarui, atau dihapus dalam konteks dikelola objek, konteks objek dikelola posting pemberitahuan melalui notification center. Konteks dikelola objek yang dapat memposting tiga jenis pemberitahuan:

  • NSManagedObjectContextObjectsDidChangeNotification: Notifikasi ini diposting setiap kali record dalam konteks objek terkelola dimasukkan, diperbarui, atau dihapus.
  • NSManagedObjectContextWillSaveNotification: Notifikasi ini diposting oleh konteks objek terkelola sebelum perubahan yang tertunda dilakukan ke backing store.
  • NSManagedObjectContextDidSaveNotification: Notifikasi ini diposting oleh konteks objek yang dikelola segera setelah perubahan yang tertunda telah dilakukan ke backing store.

Isi dari notifikasi ini identik, yaitu, properti objek notifikasi adalah instance NSManagedObjectContext yang memposting notifikasi dan kamus userInfo notifikasi berisi record yang dimasukkan, diperbarui, dan dihapus.

Intinya adalah bahwa itu membutuhkan sejumlah kode boilerplate untuk menjaga agar hasil permintaan pengambilan tetap terkini. Dengan kata lain, jika kita membuat aplikasi kita tanpa menggunakan kelas NSFetchedResultsController, kita harus mengimplementasikan mekanisme yang memantau konteks objek yang dikelola untuk perubahan dan memperbarui antarmuka pengguna yang sesuai. Mari kita lihat bagaimana NSFetchedResultsController dapat membantu kita dengan tugas ini.

5. Mengatur Antarmuka Pengguna

Bekerja dengan kelas NSFetchedResultsController cukup mudah. Sebuah instance dari kelas NSFetchedResultsController mengambil permintaan mengambil dan memiliki objek delegasi. Objek NSFetchedResultsController memastikan bahwa itu membuat hasil permintaan pengambilan terkini dengan memantau konteks objek yang dikelola permintaan mengambil yang telah dijalankan.

Jika objek NSFetchedResultsController diberitahu tentang perubahan apa pun oleh objek NSManagedObjectContext dari permintaan pengambilan, itu memberitahukan delegasinya. Anda mungkin bertanya-tanya bagaimana hal ini berbeda dari view controller yang secara langsung memonitor objek NSManagedObjectContext. Keindahan kelas NSFetchedResultsController adalah bahwa ia memproses pemberitahuan yang diterimanya dari objek NSManagedObjectContext dan memberi tahu delegasi hanya apa yang perlu diketahui untuk memperbarui antarmuka pengguna dalam menanggapi perubahan ini. Metode protokol NSFetchedResultsControllerDelegate harus menjelaskan hal ini.

Signature dari metode delegasi di atas mengungkapkan tujuan sebenarnya dari kelas NSFetchedResultsController. Di iOS, kelas NSFetchedResultsController dirancang untuk mengelola data yang ditampilkan oleh UITableView atau UICollectionView. Ini memberitahu delegasinya record mana yang berubah, bagaimana memperbarui antarmuka pengguna, dan kapan melakukannya.

Jangan khawatir jika Anda masih ragu dengan tujuan atau keuntungan dari kelas NSFetchedResultsController. Ini akan lebih masuk akal setelah kami mengimplementasikan protokol NSFetchedResultsControllerDelegate. Mari kita kembali ke aplikasi kita dan menggunakan kelas NSFetchedResultsController untuk digunakan.

Langkah 1: Mengisi Storyboard

Buka storyboard utama proyek, Main.storyboard, pilih View Controller Scene, dan sematkan di controller navigasi dengan memilih Embed In > Navigation Controller dari menu Editor.

Seret objek UITableView di View Controller Scene, buat outlet di kelas TSPViewController, dan sambungkan di storyboard. Jangan lupa untuk membuat kelas TSPViewController sesuai dengan protokol UITableViewDataSource dan UITableViewDelegate.

Pilih tampilan tabel, buka Connections Inspector, dan sambungkan dataSource tampilan tabel dan delegasikan outlet ke objek View Controller. Dengan tampilan tabel dipilih, buka Attributes Inspector dan setel jumlah Prototype Cells ke 1.

Sebelum kita melanjutkan, kita perlu membuat subclass UITableViewCell untuk sel prototipe. Buat subclass Objective-C baru, TSPToDoCell, dan atur superclass ke UITableViewCell. Buat dua outlet, beri namaLabel tipe UILabel dan doneButton tipe UIButton.

Kembali ke storyboard, pilih sel prototipe di tampilan tabel, dan atur kelas menjadi TSPToDoCell di Identity Inspector. Tambahkan UILabel dan objek UIButton ke tampilan konten sel dan sambungkan outlet di Connections Inspector. Dengan sel prototipe dipilih, buka Attributes Inspector dan atur pengidentifikasi sel prototipe ke ToDoCell. Pengidentifikasi ini akan berfungsi sebagai pengidentifikasi ulang sel. Tata letak sel prototipe akan terlihat seperti screenshot di bawah ini.

Buat subkelas UIViewController baru dan beri nama TSPAddToDoViewController. Deklarasikan outlet textField dari tipe UITextField di file header view controller dan sesuaikan view controller ke protokol UITextFieldDelegate.

Sebelum kita menambahkan view controller ke storyboard, tambahkan dua tindakan berikut ke file implementasi view controller.

Buka papan cerita sekali lagi dan tambahkan item tombol bilah dengan pengenal Add di sebelah kanan bilah navigasi TSPViewController. Tambahkan view controller baru ke storyboard dan atur kelasnya ke TSPAddToDoViewController di Identity Inspector. Dengan view controller dipilih, pilih Embed In > Navigation Controller dari menu Editor.

view controller baru sekarang harus memiliki bilah navigasi. Tambahkan dua item tombol bilah ke bilah navigasi, satu di sebelah kiri dengan identitas Cancel dan satu di sebelah kanan dengan identitas Save. Hubungkan tindakan cancel: ke item tombol bilah kiri dan tindakan save: ke item tombol bilah kanan.

Tambahkan objek UITextField ke view controller view dan posisikan 20 poin di bawah bilah navigasi. Bidang teks harus tetap di 20 titik di bawah bilah navigasi. Perhatikan bahwa batasan tata letak di atas merujuk pada top layout guide, tambahan yang sangat nyaman yang ditambahkan di iOS 7.

Hubungkan bidang teks dengan outlet yang sesuai di view controller dan atur view controller sebagai delegasi bidang teks. Akhirnya, kontrol tarik dari item bilah tombol TSPViewController ke navigation controller yang TSPAddToDoViewController adalah root view controller. Setel jenis segue ke modal dan atur pengenal segue ke addToDoViewController di Attributes Inspector. Itu banyak yang harus diterima. Namun bagian yang menarik belum datang.

Langkah 2: Menerapkan Tampilan Tabel

Sebelum kita dapat mengambil aplikasi kita untuk putaran, kita perlu mengimplementasikan protokol UITableViewDataSource di kelas TSPViewController. Namun, ini adalah di mana kelas NSFetchedResultsController ikut bermain. Untuk memastikan bahwa semuanya berfungsi mengembalikan 0 dari metode tableView:numberOfRowsInSection:. Ini akan menghasilkan tampilan tabel kosong, tetapi itu akan memungkinkan kita untuk menjalankan aplikasi tanpa mengalami crash.

Langkah 3: Simpan & Batal

Buka kelas TSPAddToDoViewController dan terapkan metode cancel: dan save: seperti yang ditunjukkan di bawah ini. Kami akan memperbarui implementasinya nanti di tutorial ini.

Bangun dan jalankan aplikasi di iOS Simulator untuk melihat apakah semuanya terhubung dengan benar. Anda harus dapat mengetuk tombol tambah di kanan atas untuk membuka TSPAddToDoViewController dan mengabaikan yang terakhir dengan mengetuk tombol batal atau simpan.

6. Menerapkan Kelas NSFetchedResultsController

Kelas NSFetchedResultsController adalah bagian dari kerangka kerja Core Data dan dimaksudkan untuk mengelola hasil permintaan pengambilan. Kelas ini dirancang untuk bekerja dengan UITableView dan UICollectionView di iOS dan NSTableView di OS X. Namun, dapat digunakan untuk tujuan lain juga.

Langkah 1: Meletakkan Dasar

Sebelum kita dapat mulai bekerja dengan kelas NSFetchedResultsController, kelas TSPViewController memerlukan akses ke instance NSManagedObjectContext, instance NSManagedObjectContext yang kita buat sebelumnya di delegasi aplikasi. Mulailah dengan mendeklarasikan properti managedObjectContext tipe NSManagedObjectContext dalam file header kelas TSPViewController.

Buka Main.storyboard, pilih view controller awal storyboard, instance UINavigationController, dan atur Storyboard ID-nya ke rootNavigationController di Identity Inspector.

Dalam aplikasi metode delegasi: application:didFinishLaunchingWithOptions:, kita mendapatkan referensi ke instance TSPViewController, view controller root dari navigation controller, dan set properti managedObjectContext. yang diperbarui: application:didFinishLaunchingWithOptions metode terlihat sebagai berikut:

Jangan lupa untuk menambahkan pernyataan impor untuk kelas TSPViewController di bagian atas TSPAppDelegate.m.

Untuk memastikan semuanya bekerja, tambahkan pernyataan log berikut ke metode viewDidLoad dari kelas TSPViewController.

Langkah 2: Inisialisasi Instance NSFetchedResultsController

Buka file implementasi kelas TSPViewController dan nyatakan properti tipe NSFetchedResultsController dalam ekstensi kelas private. Beri nama properti fetchedResultsController. instance NSFetchedResultsController juga memiliki properti delegasi yang perlu mematuhi protokol NSFetchedResultsControllerDelegate. Karena instance TSPViewController akan berfungsi sebagai delegasi dari instance NSFetchedResultsController, kita perlu menyesuaikan kelas TSPViewController dengan protokol NSFetchedResultsControllerDelegate seperti yang ditunjukkan di bawah ini.

Saatnya untuk menginisialisasi instance NSFetchedResultsController. Inti dari result controller yang diambil adalah objek NSFetchRequest, karena menentukan record mana yang akan dikelola oleh result controller yang diambil. Dalam metode viewDidLoad view controller, kami menginisialisasi permintaan pengambilan dengan meneruskan @"TSPItem" ke metode initWithEntityName:. Ini seharusnya sudah akrab sekarang dan begitu juga baris berikutnya di mana kita menambahkan deskriptor pengurutan ke permintaan pengambilan untuk mengurutkan hasil berdasarkan nilai atribut createdAt pada setiap record.

Inisialisasi results controller yang diambil cukup mudah. metode initWithFetchRequest:managedObjectContext:sectionNameKeyPath:cacheName mengambil empat argumen:

  • permintaan mengambil
  • konteks objek terkelola result controller yang diambil akan memantau
  • bagian key path jika Anda ingin hasil dibagi menjadi beberapa bagian
  • nama cache jika Anda ingin mengaktifkan caching

Kami memasukan nil untuk dua parameter terakhir untuk saat ini. Argumen pertama sudah jelas, tetapi mengapa kita perlu memasukan objek NSManagedObjectContext juga? Tidak hanya diteruskan dalam konteks objek terkelola yang digunakan untuk mengeksekusi permintaan pengambilan, itu juga konteks objek terkelola yang result controller yang diambil akan memantau perubahan. Ini akan menjadi lebih jelas dalam beberapa menit ketika kita mulai mengimplementasikan metode delegasi protokol NSFetchedResultsControllerDelegate.

Akhirnya, kita perlu memberi tahu result controller yang diambil untuk mengeksekusi permintaan pengambilan yang kita lewati. Kami melakukan ini dengan memanggil performFetch: dan berikan pointer ke objek NSError. Ini mirip dengan metode executeFetchRequest:error: dari kelas NSManagedObjectContext.

Langkah 3: Menerapkan Protokol Delegasi

Dengan pengontrol hasil yang diambil diatur dan siap digunakan, kita perlu mengimplementasikan protokol NSFetchedResultsControllerDelegate. Protokol mendefinisikan lima metode, tiga di antaranya menarik bagi kami dalam tutorial ini:

  • controllerWillChangeContent:
  • controllerDidChangeContent:
  • controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

Metode pertama dan kedua memberi tahu kami ketika data resuls controller yang diambil mengelola akan dan memang berubah. Ini penting untuk memperbarui antarmuka pengguna secara setumpuk. Misalnya, sangat mungkin terjadi beberapa perubahan sekaligus. Alih-alih memperbarui antarmuka pengguna untuk setiap perubahan, kami memperbarui antarmuka pengguna setiap kali perubahan dilakukan.

Dalam contoh kita, ini bermuara pada implementasi controllerWillChangeContent: dan controllerDidChangeContent:.

Implementasi controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: agak sulit. Metode delegasi ini membutuhkan tidak kurang dari lima argumen:

  • instance NSFetchedResultsController
  • instance NSManagedObject yang berubah
  • path index saat ini record di result controller yang diambil
  • jenis perubahan, yaitu insertupdate, atau delete
  • path index baru record di result controller yang diambil, setelah perubahan

Perhatikan bahwa path index tidak ada hubungannya dengan tampilan tabel kami. NSIndexPath tidak lebih dari sebuah objek yang berisi satu atau lebih indeks untuk mewakili jalur dalam struktur hierarkis, karenanya nama kelas.

Secara internal result controller yang diambil mengelola struktur data hierarkis dan memberi tahu delegasinya ketika struktur data itu berubah. Terserah kita untuk memvisualisasikan perubahan itu, misalnya, tampilan tabel.

Implementasi controller:didChangeObject:atIndexPath:forChangeType:newIndexPath; terlihat menakutkan, tetapi biarkan saya memandu Anda melewatinya.

Ada empat jenis perubahan yang mungkin:

  • NSFetchedResultsChangeInsert
  • NSFetchedResultsChangeDelete
  • NSFetchedResultsChangeUpdate
  • NSFetchedResultsChangeMove

Nama-nama itu cukup jelas. Jika jenisnya adalah NSFetchedResultsChangeInsert, kami memberi tahu tampilan tabel untuk menyisipkan baris di newIndexPath. Demikian pula, jika jenisnya adalah NSFetchedResultsChangeDelete, kami menghapus baris di indexPath dari tampilan tabel.

Jika record diperbarui, kami memperbarui baris terkait dalam tampilan tabel dengan menerapkan configureCell:atIndexPath:, metode helper yang menerima objek UITableViewCell dan objek NSIndexPath. Kami akan mengimplementasikan metode ini sebentar lagi.

Jika jenis perubahan sama dengan NSFetchedResultsChangeMove, kami menghapus baris di indexPath dan menyisipkan baris di newIndexPath untuk mencerminkan posisi pembaruan record dalam struktur data internal results controller  yang diambil.

Langkah 4: Menerapkan Protokol UITableViewDataSource

Itu tidak terlalu sulit. Apakah itu? Menerapkan protokol UITableViewDataSource jauh lebih mudah, tetapi ada beberapa hal yang harus Anda perhatikan. Mari kita mulai dengan metode numberOfSectionsInTableView: dan tableView:numberOfRowsInSection:.

Meskipun tampilan tabel dalam aplikasi sampel kami hanya akan memiliki satu bagian, mari kita tanyakan jumlah result controller pengambilan. Kami melakukan ini dengan memanggil sections di atasnya, yang mengembalikan array objek yang sesuai dengan protokol NSFetchedResultsSectionInfo.

Objek yang sesuai dengan protokol NSFetchedResultsSectionInfo perlu mengimplementasikan beberapa metode, termasuk numberOfObjects. Ini memberi kita apa yang kita butuhkan untuk mengimplementasikan dua metode pertama protokol UITableViewDataSource.

Selanjutnya adalah tableView:cellForRowAtIndexPath: dan metode configureCell:atIndexPath:. Mulailah dengan menambahkan pernyataan impor untuk header kelas TSPToDoCell.

Implementasi tableView:cellForRowAtIndexPath: pendek, karena kami memindahkan sebagian besar konfigurasi sel untuk configureCell:atIndexPath:. Kami meminta tampilan tabel untuk sel yang dapat digunakan kembali dengan reuse identifier @"ToDoCell" dan meneruskan sel dan path index untuk configureCell:atIndexPath:.

Keajaiban terjadi di configureCell:atIndexPath:. Kami meminta result controller yang diambil untuk item di indexPath. result controller yang diambil mengembalikan instance NSManagedObject kepada kami. Kami memperbarui nameLabel dan status dari doneButton dengan meminta record untuk atribut name dan done.

Kami akan mengunjungi kembali protokol UITableViewDataSource nanti dalam tutorial ini ketika kami menghapus item dari daftar. Pertama-tama kita perlu mengisi tampilan tabel dengan beberapa data.

7. Menambahkan Record

Mari kita selesaikan tutorial ini dengan menambahkan kemampuan untuk membuat item yang harus dilakukan. Buka kelas TSPAddToDoViewController, tambahkan pernyataan impor untuk kerangka kerja Core Data, dan deklarasikan properti managedObjectContext tipe NSManagedObjectContext.

Kembali ke kelas TSPViewController dan terapkan metode prepareForSegue:sender:. Dalam metode ini, kita menetapkan properti managedObjectContext dari instance TSPAddToDoViewController. Jika Anda pernah bekerja dengan storyboard sebelumnya, maka implementasi prepareForSegue:sender: harus jelas.

Jika pengguna memasukkan teks di bidang teks TSPAddToDoViewController dan mengetuk tombol Save, kami membuat record baru, mengisinya dengan data, dan menyimpannya. Logika ini masuk ke metode save: yang kami buat sebelumnya.

Metode save: terlihat cukup mengesankan, tapi belum ada yang belum dibahas di sana. Kami membuat objek terkelola baru dengan mengirimkan instance NSEntityDescription dan instance NSManagedObjectContext. Kami kemudian mengisi objek yang dikelola dengan nama dan tanggal. Jika menyimpan konteks objek terkelola berhasil, kami mengabaikan view controller, jika tidak, kami menampilkan tampilan lansiran. Jika pengguna mengetuk tombol simpan tanpa memasukkan teks apa pun, kami juga menampilkan tampilan lansiran.

Jalankan aplikasi dan tambahkan beberapa item. Saya yakin Anda setuju bahwa kelas NSFetchedResultsController membuat proses penambahan item menjadi sangat mudah. Ini menangani pemantauan konteks objek yang dikelola untuk perubahan dan kami memperbarui antarmuka pengguna, tampilan tabel kelas TSPViewController, berdasarkan apa yang dikatakan oleh instance NSFetchedResultsController kepada kami melalui protokol NSFetchedResultsControllerDelegate.

Kesimpulan

Pada artikel berikutnya, kami akan menyelesaikan aplikasi kami dengan menambahkan kemampuan untuk menghapus dan memperbarui item yang harus dilakukan. Penting bagi Anda untuk memahami konsep-konsep yang kami bahas dalam artikel ini. Cara Core Data menyiarkan perubahan status konteks objek yang dikelola sangat penting, jadi pastikan Anda memahami ini sebelum melanjutkan.

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.