Dismissing a Modal View Using a Storyboard Segue

Dismissing a Modal View Using a Storyboard Segue

I really like Xcode storyboards even though they can be a pain to merge if you have multiple people editing them at once. I find them a great way to kickstart and prototype an app. I love to layout the flow of the entire app, visualizing all my controllers and their interconnections. The storyboard creates a nice visualization of how the app works and in many cases it will compile and run the basics without any additional code.

The one problem I have with storyboards is dealing with Modal views. When a view is presented as a modal window, it requires some way to dismiss that window when you’re done. Often, the modal view is embedded in a navigation controller with a “Done” bar button item. Something like this:

Modal View with Navigation Controller and Done Button

Now, the problem is the “Done” button. The button needs to call the dismissViewControllerAnimated:completion: selector on the presenting view controller. That means we need an outlet to connect the button, which in turn means we need a custom controller or something.

Instead, I like to use a segue. The custom segue simply dismisses the source view controller and, as a bonus, improves the visualization in the storyboard to indicate which view the done button will reveal.

First, create a custom UIStoryboardSegue that dismisses the source view controller like so:

DismissSegue.h:

#import <UIKit/UIKit.h>

@interface DismissSegue : UIStoryboardSegue

@end

DismissSegue.m:

#import "DismissSegue.h"

@implementation DismissSegue

- (void)perform {
    UIViewController *sourceViewController = self.sourceViewController;
    [sourceViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

@end

Now, create a modal segue starting from the “Done” button and ending with the original presenting view controller. You’ll notice that there is now a “dismiss” option in the modal segue types.

Dismiss in Segue Types

It doesn’t really matter where the endpoint of the segue is because all the segue does is dismiss the source view controller, it doesn’t present anything new. If you want, you could even connect the done button to the same controller it’s inside. I like to connect it to the original source of the modal presentation so that the storyboard gives a nice circular indication where the application flow goes when the view is dismissed.

Storyboard with Loop

You can try the above example using the GitHub project here.