Easy Storyboard segues in Swift

When working with a storyboard and segues, the usual method of performing a segue can be a bit cumbersome.

To deal with this, we’ve created a tiny helper called SegueManager that allows you to pass a closure to a performSegue call.

Current situation

Say you have a simple storyboard containing two view controllers: a master and a detail controller, with a segue between them:

Storyboard with Segue

Usually at the point where you’re performing the segue, the information that needs to be passed to the destination segue is also available. However we can’t directly pass it to performSegueWithIdentifier, but instead need to store it.

This is the code needed to store a string for later, and then perform the segue:


private var textForDetail: String?

@IBAction func openDetailAction(sender: UIButton) {

  // Save text for later
  textForDetail = "This is the detail screen!"

  // Kick off segue
  self.performSegueWithIdentifier("showDetail", sender: self)
}

The thing we want to pass to the detail view controller can be as simple as a single string, like it is here. But it can also be a complete view model, specific to the detail view controller.

This is the code needed to pass the stored string along to the destination view controller:


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  // Segue is underway, update destination ViewController with value set earlier
  if let vc = segue.destinationViewController as? DetailViewController {
    vc.displayText = textForDetail;
  }
}

Note that if you have want to add a second segue, to a different view controller, you need to add code in three different places;

  1. You need an extra private var for the view model of the second controller.
  2. You need to add an extra if let check to the prepareForSegue code where the private var is passed to the destination view controller.
  3. At the place where you want to perform the segue, you have to also store the second view model in the private var.

Using SegueManager

With SegueManager you can immediatly pass a closure that sets the view model. This nicely scales when using multiple segues.

You first have to create a SegueManager in the master view controller:


var segueManager: SegueManager!

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

  // Create a segue manager based on the current view controller
  segueManager = SegueManager(viewController: self)
}

Also, you still need to override prepareForSegue, but it only needs one line of code that never needs to be changed:


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  self.segueManager.prepareForSegue(segue);
}

And finally, when you want to perform a segue, you can call performSegue on the SegueManager:


segueManager.performSegue("showDetail") { segue in
  let vc = segue.destinationViewController as DetailViewController
  vc.displayText = "This is the detail screen!"
}

And that’s it! Now, when you want to add a second segue, you only need to add a second call to performSegue, no other code needs to be changed.

Conclusion

Since the SegueManager is so little code, it’s available as a single gist that you can simply copy-and-paste into your project.

I’m curious, currently CocoaPods isn’t available for Swift, but once it is, would you like a tiny library like this to be available as a pod? Or would you be happy with just the gist as it is now?

2015-03-20: Now that CocoaPods has support for Swift, I’ve turned SegueManager into a cocoapod. OS X support has also been added.

Leave a Reply

Your email address will not be published. Required fields are marked *