UINavigationBar

In this section, you are going to give the UINavigationBar a descriptive title for the UIViewController that is currently on top of the UINavigationController’s stack.

Every UIViewController has a navigationItem property of type UINavigationItem. However, unlike UINavigationBar, UINavigationItem is not a subclass of UIView, so it cannot appear on the screen. Instead, the navigation item supplies the navigation bar with the content it needs to draw. When a UIViewController comes to the top of a UINavigationController’s stack, the UINavigationBar uses the UIViewController’s navigationItem to configure itself, as shown in Figure 14.10.

Figure 14.10  UINavigationItem

Illustration shows the navigation item UINavigationItem.

By default, a UINavigationItem is empty. At the most basic level, a UINavigationItem has a simple title string. When a UIViewController is moved to the top of the navigation stack and its navigationItem has a valid string for its title property, the navigation bar will display that string (Figure 14.11).

Figure 14.11  UINavigationItem with title

Illustration shows the UINavigationItem with the title.

The title for the ItemsViewController will always remain the same, so you can set the title of its navigation item within the storyboard itself.

Open Main.storyboard. Double-click on the center of the navigation bar above the Items View Controller to edit its title. Give it a title of Homepwner (Figure 14.12).

Figure 14.12  Setting the title in a storyboard

A view controller is shown. In the navigation bar at the top, a title text that reads “Homepwner” is displayed.

Build and run the application. Notice the string Homepwner on the navigation bar. Create and tap on a row and notice that the navigation bar no longer has a title. It would be nice to have the DetailViewController’s navigation item title be the name of the Item it is displaying. Because the title will depend on the Item that is being displayed, you need to set the title of the navigationItem dynamically in code.

In DetailViewController.swift, add a property observer to the item property that updates the title of the navigationItem.

var item: Item! {
    didSet {
        navigationItem.title = item.name
    }
}

Build and run the application. Create and tap a row and you will see that the title of the navigation bar is the name of the Item you selected.

A navigation item can hold more than just a title string, as shown in Figure 14.13. There are three customizable areas for each UINavigationItem: a leftBarButtonItem, a rightBarButtonItem, and a titleView. The left and right bar button items are references to instances of UIBarButtonItem, which contain the information for a button that can only be displayed on a UINavigationBar or a UIToolbar.

Figure 14.13  UINavigationItem with everything

Illustration shows the UINavigationItem with three sub-items.

Recall that UINavigationItem is not a subclass of UIView. Instead, UINavigationItem encapsulates information that UINavigationBar uses to configure itself. Similarly, UIBarButtonItem is not a view, but holds the information about how a single button on the UINavigationBar should be displayed. (A UIToolbar also uses instances of UIBarButtonItem to configure itself.)

The third customizable area of a UINavigationItem is its titleView. You can either use a basic string as the title or have a subclass of UIView sit in the center of the navigation item. You cannot have both. If it suits the context of a specific view controller to have a custom view (like a segmented control or a text field, for example), you would set the titleView of the navigation item to that custom view. Figure 14.13 shows an example from the built-in Maps application of a UINavigationItem with a custom view as its titleView. Typically, however, a title string is sufficient.

Adding buttons to the navigation bar

In this section, you are going to replace the two buttons that are in the table’s header view with two bar button items that will appear in the UINavigationBar when the ItemsViewController is on top of the stack. A bar button item has a target-action pair that works like UIControl’s target-action mechanism: When tapped, it sends the action message to the target.

First, let’s work on a bar button item for adding new items. This button will sit on the right side of the navigation bar when the ItemsViewController is on top of the stack. When tapped, it will add a new Item.

Before you update the storyboard, you need to change the method signature for addNewItem(_:). Currently this method is triggered by a UIButton. Now that you are changing the sender to a UIBarButtonItem, you need to update the signature.

In ItemsViewController.swift, update the method signature for addNewItem(_:).

@IBAction func addNewItem(_ sender: UIButton) {
@IBAction func addNewItem(_ sender: UIBarButtonItem) {
    ...
}

Now open Main.storyboard and then open the object library. Drag a Bar Button Item to the right side of Items View Controller’s navigation bar. Select this bar button item and open its attributes inspector. Change the System Item to Add (Figure 14.14).

Figure 14.14  System bar button item

Screenshot shows the bar button item and bar item sections in the attributes inspector.

Control-drag from this bar button item to the Items View Controller and select addNewItem: (Figure 14.15).

Figure 14.15  Connecting the addNewItem: action

Figure shows the addition of new button onto the view controller.

Build and run the application. Tap the + button and a new row will appear in the table.

Now let’s replace the Edit button. View controllers expose a bar button item that will automatically toggle their editing mode. There is no way to access this through Interface Builder, so you will need to add this bar button item programmatically.

In ItemsViewController.swift, override the init(coder:) method to set the left bar button item.

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    navigationItem.leftBarButtonItem = editButtonItem
}

Build and run the application, add some items, and tap the Edit button. The UITableView enters editing mode! The editButtonItem property creates a UIBarButtonItem with the title Edit. Even better, this button comes with a target-action pair: It calls the method setEditing(_:animated:) on its UIViewController when tapped.

Open Main.storyboard. Now that Homepwner has a fully functional navigation bar, you can get rid of the header view and the associated code. Select the header view on the table view and press Delete.

Also, the UINavigationController will handle updating the insets for the table view. In ItemsViewController.swift, delete the following code.

override func viewDidLoad() {
    super.viewDidLoad()

    // Get the height of the status bar
    let statusBarHeight = UIApplication.shared.statusBarFrame.height

    let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0)
    tableView.contentInset = insets
    tableView.scrollIndicatorInsets = insets

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 65
}

Finally, remove the toggleEditingMode(_:) method.

@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 again. The old Edit and Add buttons are gone, leaving you with a lovely UINavigationBar (Figure 14.16).

Figure 14.16  Homepwner with navigation bar

Screenshot of a view controller, titled Homepwner, is shown with three labels. An Edit button at the top left, and a plus button at the top right of the controller is shown.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset