Applications are open for the Product College - Apply Now

X

In our Notes app, a user will need to create, edit and/or discard notes. To do so, we'll need to introduce bar button items.

UIBarButtonItem allows us to add additional buttons in our navigation bar.

image showing bar button items

To support the creating, editing, and discarding actions, we'll new to implement 3 new bar button items.

First, in our ListNotesTableViewController, we'll need to add a create bar button item for creating new notes.

Next, in our DisplayNoteViewController, we'll add a save bar button item for editing existing notes and a cancel button for either discarding unintended changes or popping the view controller off the navigation stack.

Navigation Items

To add UIBarButtonItem to a navigation bar in storyboard, the navigation bar must first have a Navigation Item.

If you open Main.storyboard, you can see that our ListNotesTableViewController has a Navigation Item in the Document Outline.

Existing Navigation Item

Conversely, if you look at our DisplayNoteViewController navigation bar, it doesn't have a Navigation Item yet. Let's change that now.

In Main.storyboard, add a Navigation Item to your DisplayNoteViewController navigation bar:

Add Navigation Item

Both of our storyboard view controllers should now have Navigation Items. Next, we'll add our create, save, and cancel UIBarButtonItem views.

Adding Bar Button Items

Let's start by creating a new Create Note bar button item in our ListNotesTableViewController.

In Main.storyboard, implement a new bar button item for your table view controller:

  1. Drag a UIBarButtonItem from your Object Library to the top right side of your ListNotesTableViewController navigation bar.
  2. Select the UIBarButtonItem.
  3. With the bar button item selected, navigate to the Attributes Inspector in the Utilities area.
  4. Change the System Item dropdown from Custom to Add.

Add Create Bar Button Item

One bar button item down, two more to go!

Repeat the same process above to add a save and cancel bar button item to your DisplayNoteViewController.

In Main.storyboard, implement both save and cancel buttons to your DisplayNoteViewController.

Save Cancel Bar Button Items

We've successfully added 3 new bar button items. However, if you run the app right now, tapping on them do anything.

Next, we'll need to configure each bar button item so that tapping on it performs it's expected behavior.

Bar Button Item Segues

Each time the user taps on one of our bar button items, we want to either push or pop off of our navigation stack.

In the case of our Create Note button, when a user taps on the UIBarButtonItem, the ListNotesTableViewController should segue to the DisplayNoteViewController.

Let's implement that now!

In Main.storyboard, create a segue when the user taps the Create Note bar button item and set it's identifier:

![ms-video(https://s3.amazonaws.com/mgwu-misc/Make+School+Notes/p06introductiontobarbuttonitems/createaddseguew_identifier.mp4)

Step-by-step:

  1. Select the Create Note bar button item in the navigation bar of your table view controller. It should look like a plus (+) button.
  2. Hold control and click-drag from the Create Note bar button item to the DisplayNoteViewController.
  3. In the popup, select a Action Segue of Show to create your new segue.

Next, let's set our new segue's identifier:

  1. Select the new segue that appears between your ListNotesTableViewController and DisplayNoteViewController. When the correct segue is selected, you should see the Create Note bar button item highlighted.
  2. With the segue selected, navigate to the Attributes Inspector in the Utilities area.
  3. Set the Identifier field to addNote.

With our new segue identifier, we can update prepare(for:sender:) to notify us before the segue triggered by the Create Note bar button item completes.

Open ListNotesTableViewController.swift and update the method prepare(for:sender:) to the following:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let identifier = segue.identifier else { return }

    switch identifier {
    case "displayNote":
        print("note cell tapped")

    case "addNote":
        print("create note bar button item tapped")

    default:
        print("unexpected segue identifier")
    }
}

In the code above, we update our if-statement to a switch-statement that checks for each segue identifier.

For each identifier, the switch-statement outputs a corresponding print statement to the debug console.

Now, if we build and run our app, tapping on the Create Note bar button item will segue to the DisplayNoteViewController and output a print statement to the debug console.

Next, we'll look at how to implement segues for our DisplayNoteViewController.

Unwind Segues

Both the save and cancel bar button items will need to pop the DisplayNoteViewController off the navigation stack.

Because these segues are pops, instead of pushes, we'll need to implement a special type of segue known as a unwind segue.

Unwind segues are used to pop view controllers off the navigation stack. In other words, they're used to navigate back to previous view controllers on the navigation stack.

For instance, when a user taps the Create Note bar button item, a segue is triggered and our navigation controller pushes an instance of DisplayNoteViewController to the top of our navigation stack. Then, if we tap the cancel bar button item, we can use an unwind segue to navigate back from the DisplayNoteViewController to the table view controller again.

Notes Unwind Segue Example

Segue Memory Leaks

When navigating between multiple view controllers, be careful about creating memory leaks!

When triggering show segues, a new instance of a view controller is pushed onto the navigation stack. If we were to only use show segues to navigate between view controllers, we would be continuously creating and adding new instances of view controllers onto the navigation stack. If unbounded, this could cause our app to run out of memory, potentially crashing our app!

In the image below, we only use segues to push new instances of our two view controllers onto the navigation stack. After a few segues, our navigation stack has multiple instances of both our ListNotesTableViewController and DisplayNoteViewController.

image showing no unwind segues

Bad! This is why we must be aware of our navigation stack and use unwind segues to navigate back and forth between existing instances of view controllers.

Implementing Unwind Segues

To make sure we don't keep adding new instances with show segues, let's implement our unwind segues for our DisplayNoteViewController.

Creating a unwind segue requires two steps (in order):

  1. Create a special @IBAction method in the destination view controller that we're trying to unwind to. In our case, we'll put this method in our table view controller.
  2. Create a unwind segue in our storyboard.

It's important to follow these steps in order. If we don't add our special @IBAction method in the destination view controller that we're unwinding to, we won't be able to create our unwind segue in storyboard.

Let's start with step 1. We want to unwind from DisplayNoteViewController back to ListNotesTableViewController. For us, our destination view controller will be ListNotesTableViewController.

In ListNotesTableViewController, add the following @IBAction:

@IBAction func unwindWithSegue(_ segue: UIStoryboardSegue) {

}

We don't need to add any code within our unwind IBAction. Xcode just needs to register the function definition for us to create our unwind segue in storyboard.

Next, we'll follow step 2: create our unwind segues for both cancel and save bar button items in storyboard. Let's start with our cancel bar button item.

In Main.storyboard, create a unwind segue for your cancel bar button item and give it a identifier:

![ms-video(https://s3.amazonaws.com/mgwu-misc/Make+School+Notes/p06introductiontobarbuttonitems/createcancelseguew_identifier.mp4)

Step-by-step:

  1. Select your cancel bar button item.
  2. Hold down control and click-drag from the cancel back button item to the orange exit icon on the top bar above your view controller.
  3. In the popup, selected the IBAction you created in step 1.

Next, let's give our unwind segue an identifier:

  1. Select your unwind segue. You won't see it appear in storyboard, so you'll need to select it using your Document Outline.
  2. With your segue selected, navigate to the Attributes Inspector in the Utilities area.
  3. Set the Identifier field to cancel.

Next, we'll repeat the same steps for our save bar button item's unwind segue. We don't need to repeat step 1 since our ListNotesTableViewController already has a IBAction for unwind segues.

Repeat step 2 for our DisplayNoteViewController save bar button item. Set the new unwind segue to have an identifier of save.

If you get stuck, refer back to the steps on how we previously created a unwind segue for our cancel bar button item.

When you're done, we can add code to our DisplayNoteViewController to notify us before a unwind segue completes. In addition, we can use our new identifiers to identify which segue is being triggered.

In DisplayNoteViewController.swift, add the following code to your view controller:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let identifier = segue.identifier else { return }

    switch identifier {
    case "save":
        print("save bar button item tapped")

    case "cancel":
        print("cancel bar button item tapped")

    default:
        print("unexpected segue identifier")
    }
}

In the code above, we use prepare(for:sender:) to notify us if an unwind segue from one of our bar button items is being triggered. The method prepare(for:sender:) is especially useful because we're able to prepare for navigating both back and forth between other view controllers.

Running the App

In this section, we setup new segues for our bar button items. Let's test that each of our new bar button items work!

Build and run the app. In the table view controller, click on the Create Note bar button item. Next try the cancel and save buttons. Make sure each bar button item segues and outputs the correct print statement to the debug console.

![ms-video(https://s3.amazonaws.com/mgwu-misc/Make+School+Notes/p06introductiontobarbuttonitems/barbuttonitemsegue_checkpoint.mp4)

Next, we'll look at how to start implementing our logic for our notes app!

Feedback

If you have feedback on this tutorial or find any mistakes, please open issues on the GitHub Repository or comment below.

Summer academy

An iOS Development Summer Course

Design, code and launch your own app. Locations in San Francisco and Asia

Find your location

Product College

A computer science college

Graduate into a successful career as a founder or software engineer.

Learn more