() translation by (you can also view the original English article)
Dalam lessen sebelumnya, kita meletakkan dasar untuk aplikasi daftar belanja. Dalam bagian pertama dari pelajaran ini, kita lebih lanjut mempersempit aplikasi dengan memungkinkan pengguna untuk mengedit dan menghapus item dari daftar. Kemudian kita menambahkan kemampuan untuk memilih item dari daftar untuk membuat daftar belanja.
1. menghapus item
Menghapus item dari daftar adalah tambahan yang penting dalam hal pengalaman pengguna dan kegunaan keseluruhan. Menambahkan kemampuan ini melibatkan:
- menghapus item dari pandangan controller item properti
- memperbarui tampilan tabel
- menyimpan perubahan ke disk
Mari kita lihat bagaimana ini bekerja dalam prakteknya. Pertama kita perlu menambahkan tombol edit ke bar navigasi. Dalam tampilan controller viewDidLoad() metode, membuat sebuah instance dari UIBarButtonItem dan menetapkannya ke properti rightBarButtonItem Lihat controller navigationItem properti.
Seperti yang kita lakukan pada pelajaran sebelumnya, kita membuat sebuah bar tombol item dengan menerapkan init(barButtonSystemItem:target:action:), melewati dalam. Edit, nilai anggota UIBarButtonSystemItem, diri sebagai target, dan "editItems:" sebagai pemilih.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Register Class
|
5 |
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: CellIdentifier) |
6 |
|
7 |
// Create Add Button
|
8 |
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "addItem:") |
9 |
|
10 |
// Create Edit Button
|
11 |
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Edit, target: self, action: "editItems:") |
12 |
}
|
Pelaksanaan editItems(_:) adalah hanya satu baris kode seperti yang Anda lihat di bawah ini. Bila pengguna menyentuh tombol edit, tampilan tabel toggled masuk atau keluar dari edit mode. Kita melakukan ini dengan menggunakan sedikit trik. Kami meminta tampilan tabel apakah atau tidak itu adalah dalam mode edit, yang mengembalikan nilai Bool, dan invers nilai kembali (benar menjadi salah dan sebaliknya). Metode yang kita sebut di tampilan tabel adalah setEditing(_:animated:), seorang setter khusus yang menerima parameter animasi.
1 |
func editItems(sender: UIBarButtonItem) { |
2 |
tableView.setEditing(!tableView.editing, animated: true) |
3 |
}
|
Jika Anda menjalankan aplikasi daftar belanja di simulator dan tekan tombol edit, Anda akan melihat tampilan tabel yang sedang toggled masuk dan keluar dari mode edit.






Dua metode UITableViewDataSource protokol penting untuk memungkinkan mengedit dalam tampilan tabel:
tableView(_:canEditRowAtIndexPath:)
tableView(_:commitEditingStyle:forRowAtIndexPath:)
Jika pengguna menyentuh tombol edit, tampilan tabel meminta sumber data yang baris yang akan diedit dengan mengirimkan sumber data pesan dari tableView(_:canEditRowAtIndexPath:). Jika benar dikembalikan untuk indeks tertentu, tampilan tabel memerintahkan sel tabel Lihat sesuai yang dibutuhkan untuk beralih masuk atau keluar dari mode edit, tergantung pada modus edit tampilan tabel. Ini diterjemahkan menjadi sel Lihat tabel menampilkan atau menyembunyikan kontrol pengeditan. Menerapkan metode tableView(_:canEditRowAtIndexPath:) seperti yang ditunjukkan di bawah ini untuk melihat bagaimana ini bekerja dalam prakteknya.
1 |
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { |
2 |
if indexPath.row == 1 { |
3 |
return false |
4 |
}
|
5 |
|
6 |
return true |
7 |
}
|
Di atas pelaksanaan tableView(_:canEditRowAtIndexPath:) memungkinkan pengguna untuk mengedit setiap baris dalam tampilan tabel dengan pengecualian baris kedua. Menjalankan aplikasi dalam simulator dan mencobanya.



Untuk daftar belanja aplikasi, pengguna harus dapat mengedit setiap baris dalam tampilan tabel. Ini berarti bahwa tableView(_:canEditRowAtIndexPath:) selalu harus return true.
1 |
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { |
2 |
return true |
3 |
}
|
Anda mungkin telah memperhatikan bahwa tidak ada yang terjadi ketika Anda mencoba untuk menghapus sebuah baris dalam tampilan tabel. Teka-teki belum selesai. Bila pengguna menyentuh tombol Hapus baris, tampilan tabel mengirim sumber data pesan dari tableView(_:commitEditingStyle:forRowAtIndexPath:). Argumen kedua metode sesuai menunjukkan apa jenis tindakan pengguna telah dilakukan, memasukkan atau menghapus baris. Untuk aplikasi daftar belanja, kita hanya akan melaksanakan dukungan untuk menghapus baris dari tampilan tabel.
Menghapus baris dari tampilan tabel yang meliputi:
- menghapus item yang sesuai dari tampilan controller item properti
- memperbarui tampilan tabel dengan menghapus baris terkait
Mari kita memeriksa pelaksanaan tableView(_:commitEditingStyle:forRowAtIndexPath:). Metode dimulai dengan memeriksa apakah gaya mengedit sama. Menghapus (nilai anggota UITableViewCellEditingStyle), karena kami hanya ingin memungkinkan pengguna untuk menghapus baris dari tampilan tabel.
Jika gaya editing sama. Menghapus, item yang sesuai akan dihapus dari properti item, baris terkait akan dihapus dari tampilan tabel dan daftar diperbarui item disimpan ke disk.
1 |
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { |
2 |
if editingStyle == .Delete { |
3 |
// Delete Item from Items
|
4 |
items.removeAtIndex(indexPath.row) |
5 |
|
6 |
// Update Table View
|
7 |
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Right) |
8 |
|
9 |
// Save Changes
|
10 |
saveItems() |
11 |
}
|
12 |
}
|
Menjalankan aplikasi dalam simulator dan menghapus beberapa item. Jangan lupa untuk berhenti dan relaunch aplikasi untuk memverifikasi item yang akan dihapus secara permanen dari daftar.
2. mengedit item
Kita bisa menggunakan kembali AddItemViewController kelas untuk mengedit item. Namun, karena menggunakan satu melihat controller untuk menambah dan mengedit item dapat sering overcomplicate implementasi, aku umumnya akhirnya membuat sebuah kelas terpisah untuk mengedit item. Ini awalnya dapat mengakibatkan kita mengulangi diri kita sendiri, tetapi itu akan memberi kita lebih banyak fleksibilitas di jalan.
Langkah 1: Membuat Controller Lihat mengedit
Menciptakan subclass UIViewController baru dan nama itu EditItemViewController. Antarmuka kelas AddItemViewController dan EditItemViewController sangat mirip.
1 |
import UIKit |
2 |
|
3 |
protocol EditItemViewControllerDelegate { |
4 |
func controller(controller: EditItemViewController, didUpdateItem item: Item) |
5 |
}
|
6 |
|
7 |
class EditItemViewController: UIViewController { |
8 |
|
9 |
@IBOutlet var nameTextField: UITextField! |
10 |
@IBOutlet var priceTextField: UITextField! |
11 |
|
12 |
var item: Item! |
13 |
|
14 |
var delegate: EditItemViewControllerDelegate? |
15 |
|
16 |
...
|
17 |
|
18 |
}
|
Perbedaan adalah penambahan sebuah properti, item, untuk menyimpan referensi ke item yang sedang sedang diedit dan definisi metode protokol EditItemViewControllerDelegate. Catatan item adalah jenis Item!, dipaksa membukanya opsional. Karena mengedit item Lihat controller tidak ada gunanya tanpa item untuk mengedit, kami mengharapkan properti item untuk selalu memiliki nilai.
Buka Main.storyboard, seret sebuah instance UIViewController dari Object Library, set kelas untuk EditItemViewController dan membuat sebuah manual Tampilkan Suci segue dari daftar view controller untuk mengedit item Lihat controller. Mengatur pengenal segue EditItemViewController.



Tarik bidang teks dari perpustakaan objek ke tampilan controller tampilan dan posisi mereka seperti yang ditunjukkan pada gambar di bawah. Pilih bidang atas teks, buka Inspektur atribut, dan masukkan nama di bidang Placeholder. Pilih bidang teks dasar dan, di Inspektur atribut, mengatur teks pengganti untuk harga dan mengatur Keyboard untuk nomor Pad. Pilih tampilan controller objek, buka Inspektur koneksi, dan menghubungkan outlet yang nameTextField dan priceTextField dengan bidang teks yang sesuai di antarmuka pengguna.



Dalam tampilan controller viewDidLoad() metode, membuat Simpan tombol seperti yang kami lakukan di kelas AddItemViewController.
1 |
// MARK: -
|
2 |
// MARK: View Life Cycle
|
3 |
override func viewDidLoad() { |
4 |
super.viewDidLoad() |
5 |
|
6 |
// Create Save Button
|
7 |
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Save, target: self, action: "save:") |
8 |
}
|
Pelaksanaan tindakan save(_:) ini sangat mirip dengan yang kami dilaksanakan di kelas AddItemViewController. Ada beberapa perbedaan halus yang saya ingin menunjukkan, meskipun.
1 |
// MARK: -
|
2 |
// MARK: Actions
|
3 |
func save(sender: UIBarButtonItem) { |
4 |
if let name = nameTextField.text, let priceAsString = priceTextField.text, let price = Float(priceAsString) { |
5 |
// Update Item
|
6 |
item.name = name |
7 |
item.price = price |
8 |
|
9 |
// Notify Delegate
|
10 |
delegate?.controller(self, didUpdateItem: item) |
11 |
|
12 |
// Pop View Controller
|
13 |
navigationController?.popViewControllerAnimated(true) |
14 |
}
|
15 |
}
|
Alih-alih melewati nilai nama dan harga untuk delegasi, kita langsung update item dan lulus item diperbarui ke tampilan controller delegasi. Karena controller Lihat anak lihat controller dari controller navigasi, kita mengabaikan controller Lihat oleh bermunculan dari tumpukan navigasi.
Langkah 2: Menampilkan mengedit Item View Controller
Dalam beberapa menit, kami akan menerapkan fungsionalitas yang memungkinkan pengguna untuk memilih item dari daftar view controller untuk menambahkannya ke daftar belanja. Pengguna akan dapat melakukan hal ini dengan menekan sebuah baris dalam tampilan daftar. Pertanyaannya adalah bagaimana pengguna akan dapat mengedit item jika penyadapan baris disediakan untuk menambahkan item ke daftar belanja?
Kerangka UIKit menyediakan tombol pengungkapan detail untuk persis kasus penggunaan ini. Detail pengungkapan tombol terletak di kanan sel Lihat tabel. Untuk menambahkan detail pengungkapan tombol ke sel tampilan tabel, kita perlu meninjau kembali tableView(_:cellForRowAtIndexPath:) di daftar tampilan controller dan mengubah itu seperti yang ditunjukkan di bawah ini.
1 |
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
2 |
// Dequeue Reusable Cell
|
3 |
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) |
4 |
|
5 |
// Fetch Item
|
6 |
let item = items[indexPath.row] |
7 |
|
8 |
// Configure Table View Cell
|
9 |
cell.textLabel?.text = item.name |
10 |
cell.accessoryType = .DetailDisclosureButton |
11 |
|
12 |
return cell |
13 |
}
|
Setiap sel Lihat tabel memiliki properti accessoryType. Dalam tableView(_:cellForRowAtIndexPath:), kita set ke. DetailDisclosureButton, nilai anggota UITableViewCellAccessoryType. Anda mungkin telah memperhatikan para insinyur di Apple tidak suka nama-nama pendek.
Bagaimana tampilan tabel memberitahu para delegasi ketika tombol pengungkapan detail disadap? Tidak mengejutkan, protokol UITableViewDelegate mendefinisikan metode tableView(_:accessoryButtonTappedForRowWithIndexPath:) untuk tujuan ini. Lihatlah pelaksanaannya.
1 |
// MARK: -
|
2 |
// MARK: Table View Delegate Methods
|
3 |
override func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) { |
4 |
// Fetch Item
|
5 |
let item = items[indexPath.row] |
6 |
|
7 |
// Update Selection
|
8 |
selection = item |
9 |
|
10 |
// Perform Segue
|
11 |
performSegueWithIdentifier("EditItemViewController", sender: self) |
12 |
}
|
Kami mengambil item yang benar dari properti item dan menyimpannya dalam seleksi, properti controller Lihat daftar yang kami akan menyatakan dalam sekejap. Kami kemudian melakukan segue dengan pengenal EditItemViewController.
Sebelum kita memperbarui pelaksanaan prepareForSegue(_:sender:), kita perlu mendeklarasikan properti untuk menyimpan item yang dipilih. Kita juga perlu untuk menyesuaikan kelas ListViewController protokol EditItemViewControllerDelegate.
1 |
import UIKit |
2 |
|
3 |
class ListViewController: UITableViewController, AddItemViewControllerDelegate, EditItemViewControllerDelegate { |
4 |
|
5 |
let CellIdentifier = "Cell Identifier" |
6 |
|
7 |
var items = [Item]() |
8 |
var selection: Item? |
9 |
|
10 |
...
|
11 |
|
12 |
}
|
Diperbarui pelaksanaan prepareForSegue(_:sender:) ini cukup sederhana seperti yang Anda lihat di bawah ini. Kami mendapatkan referensi untuk mengedit item tampilan controller dan menetapkan sifat delegasi dan item. Karena pilihan properti adalah jenis Item?, kami mengikat ke item yang terus-menerus untuk aman membuka itu.
1 |
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { |
2 |
if segue.identifier == "AddItemViewController" { |
3 |
...
|
4 |
|
5 |
} else if segue.identifier == "EditItemViewController" { |
6 |
if let editItemViewController = segue.destinationViewController as? EditItemViewController, let item = selection { |
7 |
editItemViewController.delegate = self |
8 |
editItemViewController.item = item |
9 |
}
|
10 |
}
|
11 |
}
|
Pelaksanaan EditItemViewController hampir selesai. Dalam metode viewDidLoad(), kita mengisi bidang teks dengan data properti item. Karena properti teks kolom teks adalah jenis String?, kami menggunakan string interpolasi untuk membuat sebuah string dari nilai item harga properti Float. Interpolasi string cukup kuat di Swift.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Create Save Button
|
5 |
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Save, target: self, action: "save:") |
6 |
|
7 |
// Populate Text Fields
|
8 |
nameTextField.text = item.name |
9 |
priceTextField.text = "\(item.price)" |
10 |
}
|
Langkah 3: Mengadopsi protokol delegasi
Mengadopsi protokol EditItemViewControllerDelegate berarti menerapkan metode controller(_:didUpdateItem:) seperti yang ditunjukkan di bawah ini. Mungkin mengejutkan Anda bahwa kami tidak memperbarui sumber data tampilan tabel. Semua yang kita lakukan dalam metode delegasi adalah reload satu baris tampilan tabel.
1 |
// MARK: -
|
2 |
// MARK: Edit Item View Controller Delegate Methods
|
3 |
func controller(controller: EditItemViewController, didUpdateItem item: Item) { |
4 |
// Fetch Index for Item
|
5 |
if let index = items.indexOf(item) { |
6 |
// Update Table View
|
7 |
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: 0)], withRowAnimation: .Fade) |
8 |
}
|
9 |
|
10 |
// Save Items
|
11 |
saveItems() |
12 |
}
|
Alasan bahwa kita tidak perlu untuk memperbarui tampilan tabel sumber data, array item, adalah bahwa item diperbarui disahkan oleh referensi untuk mengedit item Lihat controller. Dengan kata lain, obyek yang diperbarui mengedit item Lihat controller adalah objek yang sama yang terkandung dalam array item. Ini adalah salah satu manfaat baik bekerja dengan contoh kelas. Mereka lulus oleh referensi.
Jangan lupa untuk menyimpan daftar item untuk memastikan suntingan ditulis ke disk. Jalankan aplikasi untuk menguji fungsi pengeditan.
3. menciptakan Controller Lihat daftar belanja
Sebelum kita menjelajahi sumber data dari controller Lihat daftar belanja, mari kita membuat beberapa perancah untuk bekerja dengan. Menciptakan subclass UITableViewController baru dan nama itu ShoppingListViewController.
Buka ShoppingListViewController.swift dan menambahkan dua sifat jenis [Item]:
- item, yang akan berisi daftar lengkap item
- shoppingList, yang hanya akan berisi item daftar belanja
1 |
import UIKit |
2 |
|
3 |
class ShoppingListViewController: UITableViewController { |
4 |
|
5 |
var items = [Item]() |
6 |
var shoppingList = [Item]() |
7 |
|
8 |
...
|
9 |
|
10 |
}
|
Idenya adalah untuk memuat daftar item setiap kali perubahan yang dibuat ke dalam daftar, mengurai daftar item, dan ekstrak hanya item yang memiliki properti inShoppingList diatur ke true. Barang-barang kemudian ditambahkan ke shoppingList array.
Pilihan lain akan menyimpan daftar belanja dalam file terpisah. Kelemahan dari pendekatan ini akan menjadi bahwa kita harus menjaga item dalam daftar tampilan controller dan item dalam daftar belanja disinkronisasi. Ini adalah meminta masalah jika kau bertanya padaku.
Langkah 1: Menambahkan properti pengamat
Properti pengamat adalah cara yang bagus untuk menanggapi perubahan nilai sebuah properti. Mari kita lihat bagaimana kita dapat memanfaatkan properti pengamat untuk memperbarui properti shoppingList setiap kali perubahan nilai item.
1 |
var items = [Item]() { |
2 |
didSet { |
3 |
buildShoppingList() |
4 |
}
|
5 |
}
|
Sintaks cukup mudah untuk memahami. Properti pengamat dibungkus dalam sebuah penutupan. Ada dua jenis pengamat properti:
- willSet, yang dipanggil sebelum baru nilai properti diatur
- didSet, yang dipanggil baru nilai properti diatur
Dalam contoh di atas, kita memanggil buildShoppingList() setiap kali nilai baru ditetapkan ke item. Ini adalah apa yang tampak seperti pelaksanaan buildShoppingList().
1 |
// MARK: -
|
2 |
// MARK: Helper Methods
|
3 |
func buildShoppingList() { |
4 |
shoppingList = items.filter({ (item) -> Bool in |
5 |
return item.inShoppingList |
6 |
})
|
7 |
}
|
Kami filter elemen array item, termasuk hanya item yang inShoppingList diatur ke true. Hasilnya diberikan kepada shoppingList.
Kami juga membuat seorang pengamat properti didSet untuk properti shoppingList. Di pengamat properti ini, kami memperbarui tampilan tabel untuk mencerminkan isi shoppingList, sumber data tampilan tabel.
1 |
var shoppingList = [Item]() { |
2 |
didSet { |
3 |
tableView.reloadData() |
4 |
}
|
5 |
}
|
Langkah 2: Menampilkan daftar belanja
Menerapkan metode protokol UITableViewDataSource harus menjadi permainan anak-anak sekarang. Lihatlah di bawah implementasi.
1 |
// MARK: -
|
2 |
// MARK: Table View Data Source Methods
|
3 |
override func numberOfSectionsInTableView(tableView: UITableView) -> Int { |
4 |
return 1 |
5 |
}
|
6 |
|
7 |
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
8 |
return shoppingList.count |
9 |
}
|
10 |
|
11 |
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
12 |
// Dequeue Reusable Cell
|
13 |
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) |
14 |
|
15 |
// Fetch Item
|
16 |
let item = shoppingList[indexPath.row] |
17 |
|
18 |
// Configure Table View Cell
|
19 |
cell.textLabel?.text = item.name |
20 |
|
21 |
return cell |
22 |
}
|
Jangan lupa untuk menyatakan pengenal kembali sel dan mendaftar kelas UITableViewCell seperti yang kami lakukan di kelas ListViewController.
1 |
import UIKit |
2 |
|
3 |
class ShoppingListViewController: UITableViewController { |
4 |
|
5 |
let CellIdentifier = "Cell Identifier" |
6 |
|
7 |
...
|
8 |
|
9 |
}
|
1 |
// MARK: -
|
2 |
// MARK: View Life Cycle
|
3 |
override func viewDidLoad() { |
4 |
super.viewDidLoad() |
5 |
|
6 |
// Register Class
|
7 |
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: CellIdentifier) |
8 |
}
|
Langkah 3: Loading item
Seperti yang saya jelaskan sebelumnya, keuntungan utama menggunakan daftar item untuk menyimpan dan membangun daftar belanja adalah bahwa aplikasi toko setiap item dalam hanya satu tempat. Hal ini membuat update item dalam daftar dan daftar belanja kurang dari sakit kepala. Metode loadItems() dan pathForItems() identik dengan yang kami dilaksanakan di kelas ListViewController.
1 |
private func loadItems() { |
2 |
if let filePath = pathForItems() where NSFileManager.defaultManager().fileExistsAtPath(filePath) { |
3 |
if let archivedItems = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? [Item] { |
4 |
items = archivedItems |
5 |
}
|
6 |
}
|
7 |
}
|
1 |
private func pathForItems() -> String? { |
2 |
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) |
3 |
|
4 |
if let documents = paths.first, let documentsURL = NSURL(string: documents) { |
5 |
return documentsURL.URLByAppendingPathComponent("items").path |
6 |
}
|
7 |
|
8 |
return nil |
9 |
}
|
Bila Anda menemukan duplikasi code, Anda harus mendengar dering Bel alarm. Duplikasi code tidak bermasalah sementara Anda sedang mengimplementasikan fitur baru. Setelah itu, namun, Anda harus mempertimbangkan refactoring kode Anda untuk meminimalkan jumlah duplikasi di basis kode aplikasi. Ini adalah konsep yang sangat penting dalam pengembangan perangkat lunak dan sering disebut sebagai kering, jangan ulangi dirimu sendiri. Chris Peters menulis sebuah artikel besar pada Envato Tuts + tentang pemrograman kering.
Sebelum kita menempatkan kelas ShoppingListViewController untuk menggunakan, kita perlu memperbarui metode viewDidLoad() kelas. Selain menetapkan judul tampilan controller, kami juga memuat daftar item, yang secara otomatis populates shoppingList array kita lihat sebelumnya.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Set Title
|
5 |
title = "Shopping List" |
6 |
|
7 |
// Load Items
|
8 |
loadItems() |
9 |
|
10 |
// Register Class
|
11 |
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: CellIdentifier) |
12 |
}
|
Langkah terakhir adalah untuk menginisialisasi controller Lihat daftar belanja dengan memperbarui storyboard. Ini melibatkan menambahkan contoh UITableViewController, pengaturan kelasnya untuk ShoppingListViewController, penempatan dalam controller navigasi, dan menciptakan hubungan yang suci segue antara tab bar controller dan pengontrol navigasi. Pilih tampilan tabel daftar belanja tampilan controller dan atur jumlah sel-sel prototipe ke 0.



Jalankan aplikasi untuk melihat apakah semuanya berfungsi dengan benar. Tentu saja, daftar belanja saat ini kosong dan kami tidak memiliki cara untuk menambahkan item ke daftar belanja. Mari kita perbaiki itu di langkah berikutnya.
4. menambahkan item ke daftar belanja
Seperti yang saya tulis sebelumnya, Idenya adalah untuk menambahkan item ke daftar belanja ketika tapped di daftar Lihat controller. Untuk meningkatkan pengalaman pengguna, jika item hadir dalam daftar belanja, kami menunjukkan tanda centang hijau di sebelah kiri dari nama item. Jika item yang sudah di daftar belanja disadap, itu akan dihapus dari daftar belanja dan tanda centang hijau menghilang. Ini berarti bahwa kita perlu Lihatlah metode tableView(_:didSelectRowAtIndexPath:) protokol UITableViewDelegate.
Sebelum kita menerapkan tableView(_:didSelectRowAtIndexPath:), men-download file sumber pelajaran ini. Dalam folder bernama sumber daya, menemukan file bernama checkmark.png dan checkmark@2x.png. Menambahkan kedua file ini ke proyek, karena kita perlu mereka dalam beberapa saat.
Dalam baris pertama dari tableView(_:didSelectRowAtIndexPath:), kita mengirim tampilan tabel pesan deselectRowAtIndexPath(_:animated:) untuk Hapus baris pengguna disadap. Setiap kali berturut-turut disadap, itu hanya boleh disorot untuk sekejap maka penambahan ini. Selanjutnya, kami mengambil item yang sesuai dengan pilihan pengguna dan memperbarui properti inShoppingList item (benar menjadi salah dan sebaliknya).
1 |
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { |
2 |
tableView.deselectRowAtIndexPath(indexPath, animated: true) |
3 |
|
4 |
// Fetch Item
|
5 |
let item = items[indexPath.row] |
6 |
|
7 |
// Update Item
|
8 |
item.inShoppingList = !item.inShoppingList |
9 |
|
10 |
// Update Cell
|
11 |
let cell = tableView.cellForRowAtIndexPath(indexPath) |
12 |
|
13 |
if item.inShoppingList { |
14 |
cell?.imageView?.image = UIImage(named: "checkmark") |
15 |
} else { |
16 |
cell?.imageView?.image = nil |
17 |
}
|
18 |
|
19 |
// Save Items
|
20 |
saveItems() |
21 |
}
|
Berdasarkan nilai item inShoppingList properti, kita baik menampilkan atau menyembunyikan tanda centang hijau. Kami menunjukkan tanda centang dengan mengatur properti gambar pemandangan sel tabel imageView properti. Sel Lihat tabel termasuk gambar pemandangan kiri (instance kelas UIImageView). Dengan mengatur tampilan gambar gambar properti Nil, tampilan gambar kosong, menampilkan tidak ada gambar.
Pelaksanaan tableView(_:didSelectRowAtIndexPath:) berakhir dengan menyimpan daftar item ke disk untuk memastikan bahwa perubahan permanen.
Bagaimana daftar belanja tahu Kapan item dalam daftar view controller disadap oleh pengguna? Lihat daftar belanja controller tidak akan update tampilan tabel yang secara otomatis jika perubahan yang dibuat ke daftar item dalam daftar Lihat controller. Untuk mencegah coupling ketat, kami tidak ingin daftar tampilan controller dan controller Lihat daftar belanja untuk berkomunikasi secara langsung dengan satu sama lain.
Salah satu solusi untuk masalah ini adalah penggunaan pemberitahuan. Setiap kali daftar view controller melakukan perubahan ke daftar item, itu posting pemberitahuan dengan nama spesifik ke pemberitahuan pusat, objek yang mengelola pemberitahuan. Benda-benda yang tertarik dalam pemberitahuan tertentu dapat menambahkan diri mereka sebagai pengamat pemberitahuan tersebut, yang berarti bahwa mereka bisa berespon ketika pemberitahuan tersebut dikirim ke pusat pemberitahuan.
Bagaimana semua ini bekerja? Ada tiga langkah yang terlibat:
- Lihat daftar belanja controller dimulai dengan mengatakan pusat pemberitahuan bahwa ia tertarik menerima pemberitahuan dengan nama ShoppingListDidChangeNotification
- Daftar view controller posting pemberitahuan ke pusat pemberitahuan setiap kali Diperbarui daftar item
- Ketika controller Lihat daftar belanja menerima pemberitahuan dari pusat pemberitahuan, memperbarui tampilan data dengan sumber dan meja di respon
Sebelum kita menerapkan tiga langkah yang baru saja dijelaskan, adalah ide yang baik untuk mengambil melihat lebih dekat kelas NSNotificationCenter.
Singkatnya, NSNotificationCenter mengelola Penyiaran pemberitahuan. Objek dalam aplikasi dapat mendaftar dengan pusat pemberitahuan untuk menerima pemberitahuan menggunakan addObserver(_:selector:name:object:) dimana:
- Argumen pertama adalah obyek yang akan menerima pemberitahuan (pengamat)
- pemilih adalah tindakan yang disebut pada pengamatnya ketika menerima pemberitahuan
- Nama adalah nama pemberitahuan
- objek adalah objek yang memicu pengiriman pemberitahuan
Jika argumen terakhir diatur ke nol, pengamat menerima setiap pemberitahuan dengan nama tertentu.
Langkah 1: Menerima pemberitahuan
Meninjau metode viewDidLoad() kelas ShoppingListViewController dan menambahkan instance controller lihat sebagai pengamat untuk menerima pemberitahuan dengan nama ShoppingListDidChangeNotification.
1 |
override func viewDidLoad() { |
2 |
super.viewDidLoad() |
3 |
|
4 |
// Set Title
|
5 |
title = "Shopping List" |
6 |
|
7 |
// Load Items
|
8 |
loadItems() |
9 |
|
10 |
// Register Class
|
11 |
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: CellIdentifier) |
12 |
|
13 |
// Add Observer
|
14 |
NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateShoppingList:", name: "ShoppingListDidChangeNotification", object: nil) |
15 |
}
|
Tindakan yang dipicu ketika tampilan controller menerima pemberitahuan dengan nama itu adalah updateShoppingList(_:). Terakhir parameter, objek, nil, karena tidak peduli objek yang mengirimkan pemberitahuan.
Langkah 2: Menanggapi pemberitahuan
Metode yang dipicu ketika pengamat menerima pemberitahuan memiliki format tertentu seperti yang Anda lihat di bawah ini. It menerima satu argumen, objek pemberitahuan yang merupakan jenis NSNotification.
Objek pemberitahuan membuat referensi ke obyek yang diposting pemberitahuan dan juga dapat berisi Kamus dengan informasi tambahan. Pelaksanaan metode updateShoppingList(_:) cukup sederhana. Kita memanggil loadItems() pada view controller, yang berarti bahwa daftar item penuh dari disk. Sisanya terjadi secara otomatis berkat pengamat properti kami menerapkan sebelumnya.
1 |
// MARK: -
|
2 |
// MARK: Notification Handling
|
3 |
func updateShoppingList(notification: NSNotification) { |
4 |
loadItems() |
5 |
}
|
Langkah 3: Mengirimkan pemberitahuan
Ketiga potongan teka-teki adalah posting pemberitahuan setiap kali daftar item berubah oleh daftar Lihat controller. Kita dapat melakukan ini dalam metode saveItems() kelas ListViewController.
1 |
private func saveItems() { |
2 |
if let filePath = pathForItems() { |
3 |
NSKeyedArchiver.archiveRootObject(items, toFile: filePath) |
4 |
|
5 |
// Post Notification
|
6 |
NSNotificationCenter.defaultCenter().postNotificationName("ShoppingListDidChangeNotification", object: self) |
7 |
}
|
8 |
}
|
Kami pertama kali meminta referensi ke default pemberitahuan pusat dengan menelepon defaultCenter() pada kelas NSNotificationCenter. Selanjutnya, kita sebut postNotificationName(_:object:) di pusat pemberitahuan default, melewati dalam nama pemberitahuan, ShoppingListDidChangeNotification, dan objek posting pemberitahuan.
Sebelum Anda membangun proyek, pastikan untuk mengubah tableView(_:cellForRowAtIndexPath:) di ListViewController.swift seperti yang ditunjukkan di bawah ini untuk menampilkan tanda centang hijau untuk item yang sudah ada di daftar belanja.
1 |
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
2 |
// Dequeue Reusable Cell
|
3 |
let cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) |
4 |
|
5 |
// Fetch Item
|
6 |
let item = items[indexPath.row] |
7 |
|
8 |
// Configure Table View Cell
|
9 |
cell.textLabel?.text = item.name |
10 |
cell.accessoryType = .DetailDisclosureButton |
11 |
|
12 |
if item.inShoppingList { |
13 |
cell.imageView?.image = UIImage(named: "checkmark") |
14 |
} else { |
15 |
cell.imageView?.image = nil |
16 |
}
|
17 |
|
18 |
return cell |
19 |
}
|
Menjalankan aplikasi daftar belanja untuk memberikan spin. Pernahkah Anda memperhatikan bahwa suntingan ke item secara otomatis tercermin dalam daftar belanja?



Siap untuk publikasi?
Hebat. Dimana ada tombol untuk menerbitkan daftar belanja aplikasi untuk App Store? Kami belum cukup selesai. Meskipun kami telah meletakkan dasar aplikasi daftar belanja, hal ini tidak siap untuk publikasi. Ada juga beberapa hal untuk dipertimbangkan.
Skalabilitas
Aplikasi daftar belanja adalah implementasi daftar belanja yang sederhana. Jika aplikasi berisi ratusan atau ribuan item maka akan berkaitan dengan menambahkan kemampuan pencarian serta bagian mengurutkan item menurut abjad (seperti yang kita lakukan sebelumnya dalam seri ini). Penting untuk menyadari bahwa daftar item ditulis ke disk secara keseluruhan setiap kali item diperbarui. Hal ini tidak ada masalah ketika daftar kecil, tetapi itu akan jika daftar tumbuh dari waktu ke waktu untuk ratusan atau ribuan item.
Hubungan
Juga, pengguna mungkin ingin menyimpan lebih dari satu daftar belanja. Bagaimana Anda berurusan dengan itu? Salah satu pilihan adalah untuk menyimpan setiap daftar belanja dalam file terpisah, tapi bagaimana Anda akan menghadapi perubahan yang dibuat ke item? Apakah Anda akan memperbarui daftar setiap belanja yang berisi item? Ketika Anda mulai berurusan dengan hubungan, itu lebih baik untuk memilih untuk penyimpanan data SQLite.
Data inti adalah menjadi pendamping bagus jika Anda memilih untuk pergi menyusuri jalan itu. Ini adalah kerangka kerja yang kuat dan olahraga banyak fitur yang membuat banyak kode dalam aplikasi daftar belanja kami usang. Memang benar bahwa Data inti membawa sedikit lebih banyak overhead dengan itu jadi kunci pertama mempertimbangkan jika Data inti ini cocok untuk aplikasi Anda, dengan kata lain, apakah hal itu layak overhead.
Fitur tambahan
Ada juga banyak potensi untuk fitur tambahan. Harga properti item tetap tidak terpakai dalam implementasi saat ini aplikasi daftar belanja. Juga, akan lebih baik jika pengguna dapat memeriksa off item dari daftar belanja dengan menekan item. Seperti yang Anda lihat, implementasi saat ini aplikasi daftar belanja adalah hanya awal yang sederhana.
Kesimpulan
Meskipun aplikasi daftar belanja tidak cukup siap untuk App Store, Anda tidak dapat menyangkal bahwa itu bekerja seperti yang direncanakan dan ini telah menunjukkan Anda beberapa aspek baru pengembangan kakao, seperti pemberitahuan dan mengimplementasikan protokol kustom delegasi.
Anda sekarang tahu apa yang diharapkan dari iOS SDK dan pembangunan iOS apa seperti. Terserah kepada Anda untuk memutuskan apakah Anda ingin melanjutkan perjalanan dan menjadi seorang pengembang terampil iOS. Jika Anda memilih untuk melanjutkan dengan iOS pengembangan, maka saya akan memberikan Anda dengan beberapa sumber daya yang besar dalam angsuran berikutnya dan akhir dari seri ini.
Jika Anda memiliki pertanyaan atau komentar, Anda dapat meninggalkannya di komentar di bawah atau menghubungi saya di Twitter.