Hands-On Full:Stack Development with Swift
上QQ阅读APP看书,第一时间看更新

Editing the list

Adding the ability to edit the list of items by either deleting them or rearranging them is easy as well. All we need to do is implement few more methods to let our ItemTableViewController know that we want to delete certain rows or rearrange them and write code to update our model representing the list, which is our array of items.

First, let's implement deleting. To turn on deleting, we need to perform the following steps:

  1. Implement the tableView(_:canEditRowAt:) method. In this method, we need to return true and it will allow deleting of all rows and hence all Shopping List Items. Setting this to true will allow users to swipe the cell to the left to reveal the Delete button, or it can be swiped all the way to the left to trigger a delete:
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
  1. Implement tableView(_:commit:forRowAt:). In this method, we need to delete the row from the table and also remove the item from our array of items. In the following code, we are checking whether the editingStyle is delete and if it is, then we remove the item from the array and, also delete the row from the tableView with a fade animation:
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
items.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
  1. Add an edit button to the navigation bar, which is another way to indicate to the user that the cell is editable and can be deleted. To add the edit button, all we need to do is add the following code to the viewDidLoad method:
self.navigationItem.rightBarButtonItems?.append(editButtonItem)

Let's try this out by running the app. You should see the edit button and also swiping to the left will reveal a Delete option below the cell, swiping all the way to the left will delete the row and the item. Cool!:

Now, let's add the ability to rearrange the list as part of our feature to edit the list. To do so again, we need to implement two more methods:

  1. Add the tableView(_:canMoveRowAt:) method and return true for all rows:
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
  1. Implement the rearranging logic to update our model. It's as easy as removing an item from our array and inserting it into a new index:
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let item = items.remove(at: fromIndexPath.row)
items.insert(item, at: to.row)
}

Run the app again. Now, when we tap on the Edit button, you will now see three horizontal bars next to each cell indicating that it can be rearranged. Moving one cell to another will also update our model behind the scenes:

Only one thing is left now in terms of editing items our list, and that's checking and unchecking the items. We can do so by listening for the selection of a cell as an indicator to toggle an item between the checked and unchecked state. To achieve this, we need to do the following:

  1. Add the tableView(_:didSelectRowAt:) method to our ItemTableViewController.swift file. This method is called every time user selects a cell via a tap. The indexPath, which contains the section and row information, is passed in the argument, which we can use to figure out which item was selected.
  2. Using the indexPath, we figure out that it's the following item:
let item = items[indexPath.row]
  1. Toggle the isChecked state:
item.isChecked = !item.isChecked
  1. Tell tableView to reload the cell whose model was just edited and it will cause the cell to refresh:
tableView.reloadRows(at: [indexPath], with: .middle)

So the entire method block would look like this

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
item.isChecked = !item.isChecked
tableView.reloadRows(at: [indexPath], with: .middle)
}

Try it out by running the app and it will toggle the check mark next to the right of the cell and animate it.