Protocol-Oriented Segue Identifiers in Swift

Back in August, I watched the phenomenal Swift in Practice WWDC15 Session. I wrote about the first part of the video that impressed me – A Beautiful Solution to Non-Optional UIImage Named in Swift – and I’m finally getting around to writing about the second and even more exciting part of that video (after all, holidays are best for catching up on blogging!).

This time, I’ll be writing about an elegant solution to handling multiple segue identifiers. You guessed it! There will be protocols.

So today, we’re going on a journey of your choice. You choose: the red pill or the blue pill…

Matrix Red Pill Blue Pill App

The Problem

Unfortunately, Segue Identifiers are hard-coded String based. When you add them inΒ your Storyboard, you have to copy the string everywhere in your code – accidental misspellings are just ready to happen.

And of course, if you decide to change the name of the segue identifier in the future, you have to change it in every place it was hard-coded… more potential for accidental copy / paste accidents and misspellings.

To mitigate this, I use enums to deal with my segue identifiers whenever there is more than one segue identifier in my ViewController.

But that presents another set of problems… Mainly, it’s bloated and ugly:

The problem becomes a lot worse when dealing with this in prepareForSegue:

This was my actual code before Swift 2.0. Now you can at least use guard to deal with the Pyramid of Doom, but it’s still not great:

Anyway, this is the problems you’ll have to deal with in every single one of your view controllers throughout your app. So how can you clean it up? Again, you guess it! Protocols to the rescue!

The Solution

The solution is very elegant, and not something I would have come up with myself. Thanks Apple for the great architecture talks at WWDC this year. Seriously, these are awesome!

First, you create a SegueHandlerType that identifies the SegueIdentifier enum as a type:

Now you can use the power of protocol extensions to create methods for UIViewControllers with String-based SegueIdentifier enums:

Notice that the methods in the protocol extensions are not declared in the protocol – they’re not meant to be overwritten. The best use-case for this I’ve seen.

So now, using these is simple and beautiful:


From the video, the benefits of using the SegueHandlerType are:

  • Compiler errors when adding new segues if the new case isn’t handled
  • Reusable
  • Convenient syntax

We also get to see the power of Protocols:

  • Tighten app constraints using protocols with associated types
  • Share implementation through a constrained protocol extension

The most powerful lesson here is to take advantage of the compiler. If you structure your code in this way, the compiler will work with you, warning you when you’re missing cases!

You can view the full sample code on Github here.

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.

  • Maxim Pervushin

    How about that?

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let redPillVC = segue.destinationViewController as? RedPillVC {
    } else if let bluePillVC = segue.destinationViewController as? BluePillVC {

    • Victor Ilyukevich

      You might use same view controller for multiple segues. Segue identifier makes it unique, not a destinationViewController.

      • Maxim Pervushin

        Yes, you can use segue identifier to configure two identical view controllers different ways. But it is only 1% of all situations. I can hardly imagine when you may need to do such things.

        • Victor Ilyukevich

          An example from top of my head. We use the same view controller to edit and to add a new object. From the list screen user can go to add a new object or to edit an existent one. In both cases there would be the same destinationViewController class, but different segue identifiers.

    • Farzad Sharbafian

      It can be covered with something like:

      func destination(forSegue segue: UIStoryboardSegue) -> T {

      guard let viewController = segue.destination as? T else {

      fatalError(“Invalid Destination ViewController: (T.self) bounded to Segue: (segueIdentifier(forSegue: segue)), “)


      return viewController


      and afterwards it can be used like:
      let destinationVc = destination(forSegue: segue) as CustomViewController

      sure, it still works on run-time, but at least we’ll have a clean code and don’t have to downcast in our code, all the time.

  • Vik78

    I’m sorry, I don’t think this is a better solution than hardcoding the values of the segue identifier. I really like getting the errors from the compiler, but you’re wrapping some functionality just so you get that. Now you have more code to be read and understood by the next programmer that comes by.

    Have a look at this, specially from 25:50.

    • Your argument isn’t very strong. Natasha’s helper methods work just like any other means of removing duplication. Of course that code has to be understood at least once. Afterwards segue handling code is much more concise, though.

  • You can also use SwiftGen to generate exactly the same kind of code (enums for storyboard segues), but generated automatically for you!

  • swiftymatt

    This is brilliant Natasha. I’ve been using enums for segues and can’t believe I didn’t think of implementing the protocol extensions… πŸ™

  • I like the result. I worry about local coupling of SegueHandlerType and SegueIdentifier, though. You cannot just invoke any segue possible anymore — it has to be included in the segue-handling view controller’s SegueIdentifier enum. That possibly entails duplication of identifiers. Any thoughts on that?

  • specialvict

    Hi, Natasha, that is great pleasure to read your article, it’s really helpful.

  • Yes, it’s pretty, but IMHO this is a bit of an over-engineering.

    I define segue naming constants in the view controllers (in the files, not classes) that will get presented by those segues. This way you have segue identifiers available in whole project, but they are not lumped up in single place and it also avoids identifier duplication. Performing segues stays the same too (just passing string constant as an argument).

  • alpha

    it’s just a string, define a constant for each viewController (static let IDENTIFIER = “TheRedPillExperience” and refer to them in your function calls as RedViewController.IDENTIFIER, that’s what constants are for. Protocols enabled communication between two unrelated objects and not for storing seque identifiers

    • Farzad Sharbafian

      Natasha’s answer is actually how Swift Developers in apple say we should use Swift.

  • Mark Patterson

    This is neat. There seems to be a lot of tricks for extracting patterns once you master it.

  • Fred Adda

    I love it! Adopted!

  • snit_ram

    It would be great to also encapsulate the type of the destinationViewController to avoid downcasting all the time

  • ε―θ’™ζ¨Š

    Thanks for sharing good articles

  • Michael Sewell

    The syntax for this has changed slightly in Swift 3, see this gist for the updated syntax:

  • Shabeer S Hussain

    Brilliant – anything to limit the use of hard coded strings, use of enums are just a beautiful bonus. Up until now i was doing the same of created enums in the view controller.

    With a slight change to syntax, I uploaded a variation to github

  • Daniel Creagh

    Top quality stuff!

  • Dope! Thanks πŸ™‚

  • Vahids

    What’s wrong on this design:

    // segue ways identifiers
    public struct SegueIdentifier {
    public struct Setup {
    static var ShowSetup = “showSetupPage”
    static var ShowDashboard = “showDashboardPage”
    static var ShowStart = “showStartPage”
    public struct Settings {
    static var GotoAbout = “gotoAbout”
    static var GotoViewSettings = “gotoViewSettings”

    Easy to implement, easy to access:
    performSegueWithIdentifier(SegueIdentifier. Settings.GotoAbout, sender: self)

  • Radek

    Hey and what about when my view controller inherits from UITableViewController? I’m not able to run performSegueWithIdentifier function on it…