In the last chapter, you created an application that displays a list of Item instances in a UITableView. The next step is allowing the user to interact with the table – to add, delete, and move rows. Figure 11.1 shows what Homepwner will look like by the end of this chapter.
UITableView has an editing property, and when this property is set to true, the UITableView enters editing mode. Once the table view is in editing mode, the rows of the table can be manipulated by the user. Depending on how the table view is configured, the user can change the order of the rows, add rows, or remove rows. (Editing mode does not allow the user to edit the content of a row.)
But first, the user needs a way to put the UITableView in editing mode. For now, you are going to include a button in the header view of the table. A header view appears at the top of a table and is useful for adding section-wide or table-wide titles and controls. It can be any UIView instance.
Note that the table view uses the word “header” in two different ways: There can be a table header and section headers. Likewise, there can be a table footer and section footers (Figure 11.2).
You are creating a table header view. It will have two subviews that are instances of UIButton: one to toggle editing mode and the other to add a new Item to the table. You could create this view programmatically, but in this case you will create the view and its subviews in the storyboard file.
First, let’s set up the necessary code. Reopen Homepwner.xcodeproj. In ItemsViewController.swift, stub out two methods in the implementation.
class ItemsViewController: UITableViewController { var itemStore: ItemStore! @IBAction func addNewItem(_ sender: UIButton) { } @IBAction func toggleEditingMode(_ sender: UIButton) { }
Now open Main.storyboard. From the object library, drag a View to the very top of the table view, above the prototype cell. This will add the view as a header view for the table view. Resize the height of this view to be about 60 points. (You can use the size inspector if you want to make it exact.)
Now drag two Buttons from the object library to the header view. Change their text and position them as shown in Figure 11.3. You do not need to be exact – you will add constraints soon to position the buttons.
Select both of the buttons and open the Auto Layout Align menu. Select Vertically in Container with a constant of 0. Make sure Update Frames is set to None, and then click Add 2 Constraints (Figure 11.4).
Open the Add New Constraints menu and configure it as shown in Figure 11.5. Make sure the values for the leading and trailing constraints save after you have typed them; sometimes the values do not save, so it can be a bit tricky. When you have done that, click Add 4 Constraints.
Finally, connect the actions for the two buttons as shown in Figure 11.6.
Build and run the application to see the interface.
Now let’s implement the toggleEditingMode(_:) method. You could toggle the editing property of UITableView directly. However, UIViewController also has an editing property. A UITableViewController instance automatically sets the editing property of its table view to match its own editing property. By setting the editing property on the view controller itself, it can ensure that other aspects of the interface also enter and leave editing mode. You will see an example of this in Chapter 14 with UIViewController’s editButtonItem.
To set the isEditing property for a view controller, you call the method setEditing(_:animated:). In ItemsViewController.swift, implement toggleEditingMode(_:).
@IBAction func toggleEditingMode(_ sender: UIButton) { // If you are currently in editing mode... if isEditing { // Change text of button to inform user of state sender.setTitle("Edit", for: .normal) // Turn off editing mode setEditing(false, animated: true) } else { // Change text of button to inform user of state sender.setTitle("Done", for: .normal) // Enter editing mode setEditing(true, animated: true) } }
Build and run your application. Tap the Edit button and the UITableView will enter editing mode (Figure 11.7).