How Do Unwind Segues Work

Unwind segues, introduced in iOS 6, cause quite a bit of confusion among developers. Even if you are used to working with storyboards, you may have stayed clear from unwind segues because you don't exactly know what they are or how they work. This article resolves that problem. In this tutorial, I explain the nuts and bolts of unwind segues.

Project Setup

Create a new Xcode project based on the Single View Application template and name it Unwinding. Set Language to Swift and Devices to iPhone.

Choose the Single View Application Template

Configure the Project

The project already includes a UIViewController subclass, ViewController. For this example, we need another UIViewController subclass. Create a new class by selecting New > File... from Xcode's File menu. Select Cocoa Touch Class from the iOS > Source section and click Next. Name the class RootViewController and set Subclass of: to UIViewController. Set Language to Swift and make sure Also create XIB file is unchecked.

Create the Root View Controller Class

Storyboard Setup

Add a Navigation Controller

You probably already know that segues and storyboards work very well together. Unwind segues are no different. Before we can add an unwind segue, we need a navigation hierarchy to work with. Open Main.storyboad and select the view controller of the View Controller Scene. Open the Identity Inspector on the right and set Class to RootViewController.

With the view controller selected, choose Embed In > Navigation Controller from Xcode's Editor menu. The root view controller is now the root view controller of a navigation controller. This is what we have so far.

Embedding the Root View Controller In a Navigation Controller

Create Segues

To make the storyboard a bit more interesting, drag two UIViewController instances from the Object Library to the workspace. Select the first UIViewController instance and set Class to ViewController in the Identity Inspector. The class of the second UIViewController should remain UIViewController.

Add a button to the root view controller, center it in the view controller's view, and set its title to Show. To navigate from the root view controller to the ViewController instance, we need to create a segue. Press Control and drag from the button in the root view controller to the view controller, selecting Show from the menu that pops up. That is one segue created.

Add two buttons to the ViewController instance, Back and Forward. Create a Show segue from the Forward button to the UIViewController instance. The Back button will trigger an unwind segue.

Finally, add a Back button to the center of the UIViewController instance. This button will also trigger an unwind segue. This is what the storyboard should look like.

Adding View Controllers

You can run the application in the simulator to test the application. The Back buttons we added aren't functional yet, but remember that the navigation bar also has a Back button.

Unwind Segues

A Bit of Background

Before we add an unwind segue to the storyboard, you need to know a bit more about unwind segues. Despite their name, unwind segues differ in several ways from regular segues. For example, unwind segues always segue from the source or current view controller to an existing view controller, a view controller that is already present in the navigation hierarchy.

Unwind segues always segue from the source or current view controller to an existing view controller, a view controller that is already present in the navigation hierarchy.

What makes unwind segues powerful is their ability to unwind the navigation hierarchy one or more steps. This is something we explore a bit later. When I first read about unwind segues, I was a bit skeptical. I could not find a compelling reason to use them. After using them in a few projects, I have come to appreciate their power and flexibility.

Another interesting aspect of unwind segues is that they do not explicitly define a destination view controller. An unwind segue searches for its destination view controller at runtime by traversing the navigation hierarchy. And that is exactly what makes unwind segues powerful.

Implementation

Create Unwind Action

The first ingredient we need is an unwind action. Any view controller can define an unwind action as long as it meets the following requirements:

  • the action accepts one parameter of type UIStoryboardSegue
  • the action is prefixed with the @IBAction declaration attribute

That is all there is to it. The name of the action is not important, but it needs to be unique and descriptive in the context of the entire application. Why that is becomes clear in a moment.

Open RootViewController.swift and define the following unwind action. As you can see, the implementation is pretty basic. The unwind action is what marks a view controller as a potential destination view controller for an unwind segue.

@IBAction func unwindToRootViewController(segue: UIStoryboardSegue) {
    print("Unwind to Root View Controller")
}

The unwind action is what marks a view controller as a potential destination view controller for an unwind segue.

Create Unwind Segue

To create an unwind segue, we need to revisit Main.storyboard. Press Control and drag from the Back button of the ViewController instance to the Exit icon at the top of the scene. The unwind action we created a moment ago should be included in the menu that pops up. Select the unwind action to create the unwind segue.

Create an Unwind Segue

Create an Unwind Segue

The unwind segue should now appear in the Document Outline on the left.

Create an Unwind Segue

It is important to realize that the unwind action of the RootViewController class appeared in the menu of unwind actions. The menu lists every unwind action defined in the project. That is why you need to give unwind actions descriptive names.

The exit icon symbolizes the exit point of a view controller scene. It is possible to create multiple unwind segues for a view controller scene. Each unwind segue can have a different destination view controller.

In Main.storyboard, locate the UIViewController instance. Press Control and drag from the Back button to the Exit icon at the top. Select the same unwind action from the menu that pops up.

Run the application in the simulator to test the unwind segues we created. As you can see, it is possible to trigger the same unwind action for several unwind segues in different view controller scenes. In fact, that is one of the strengths of unwind segues.

How Do Unwind Segues Work?

Finding the Destination View Controller

When the user taps the Back button in any of the view controllers, the unwind segue you created inspects the navigation hierarchy and searches for the destination view controller of the segue. It traverses the navigation hierarchy and asks each view controller whether it can respond to the unwind action we linked to the unwind segue.

The destination view controller is not set at compile time. That is very important to understand and it is a key difference with regular segues. If the unwind segue does not find a view controller that can respond to the unwind action, the unwind segue is aborted.

Unwinding

If a destination view controller is found, a number of events are triggered. The source view controller is given the opportunity to prepare for the unwind segue in its prepareForSegue(_:sender:) method. Next, the destination view controller is notified through the invocation of the unwind action. After the source and destination view controllers have had a chance to prepare for the segue, the unwind segue is performed.

Passing Data

It is possible to pass data from the source view controller to the destination view controller in prepareForSegue(_:sender:) and in the unwind action. When prepareForSegue(_:sender:) is invoked, the destination view controller is known and accessible through the destinationViewController property of the storyboard segue. The destination view controller has access to the source view controller through the storyboard segue that is passed in as the only argument of the unwind action.

While I like the flexibility of regular and unwind segues, passing data between view controllers using segues should not be overused as it can introduce too much coupling between view controllers. Keep this in mind.

Possibilities

While unwind segues are a powerful addition to storyboards, know that unwind segues can also be triggered in code. Select the unwind segue of the ViewController instance in the storyboard, open the Attributes Inspector on the right, and set the identifier of the segue.

Configuring an Unwind Segue in Interface Builder

To trigger the (unwind) segue in code, invoke performSegueWithIdentifier(_:sender:), passing in the segue identifier and the view controller triggering the segue.

What I like about unwind segues is that you can create multiple unwind segues that unwind to the same destination view controller. The example we created illustrates this. The Back button of both view controllers trigger an unwind segue that unwinds the navigation hierarchy to the root view controller.

To end this tutorial, I would like to show you that unwind segues can be used with any type of navigation hierarchy. The complexity is irrelevant. Open Main.storyboard, add another ViewController instance, and embed it in a navigation controller. Add a button to the view controller and have it trigger the unwind action of the root view controller. You now know how to do this.

Add a bar button item to the navigation bar of the root view controller and create a segue from the bar button item to the navigation controller of which the view controller you just added is the root view controller. Make sure the segue presents the view controller modally by setting Kind to Present Modally in the Attributes Inspector.

Updating the Storyboard

Run the application in the simulator and tap the bar button item in the navigation bar to show the view controller modally. When you tap the Dismiss button, the unwind action is triggered and the unwind segue is performed. No matter how the navigation hierarchy looks, the unwind segue reaches its destination view controller without issues.

What's Next?

What we have covered in this tutorial is the most common scenario for unwind segues. But what happens if multiple instances of a view controller class with an unwind action are part of the navigation hierarchy and the unwind action is triggered? Unwind segues can handle this, but it requires a bit more work from the developer's part. I will discuss this in a future tutorial.

Questions? Leave them in the comments below or reach out to me on Twitter. You can download the source files of the tutorial from GitHub.

Stop Writing Swift That Sucks

Download the Swift Patterns I Swear By

About Bart Jacobs

About bart jacobs

My name is Bart Jacobs and I run a mobile development company, Code Foundry. I've been programming for more than fifteen years, focusing on Cocoa development soon after the introduction of the iPhone in 2007.

Stop Writing Swift That Sucks

In my free book, you learn the four patterns I use in every Swift project I work on. You learn how easy it is to integrate these patterns in any Swift project.