You know the story: you have an app laid out as storyboard, want to show a modal view controller and when the user is done with it it you want to dismiss it, … or un-present it, or whatever you need to get rid of the modal VC and return. Now what about a view controller that can be both presented modally or via push onto a navigation controller?
Then it starts to get complicated. Unless you know about how to unwind. It’s actually quite awesome, but you have to use it several times because it is a little bit counter-intuitive how to implement unwinding. I’m writing this tutorial so that I myself can remember how to do it in the future.
Unwind segues were introduced with iOS 6. If you don’t support iOS 5 any more then you should start using them today if you have not know about them until reading this here blog post. I think they provide a welcome simplification of your dismissal code.
For this tutorial, let’s assume that you have a fancy view controller which can both be used for adding or editing something. For adding you want to show it modally. For editing you want to show it via a push segue. So let’s put together a storyboard like so:
As you can see on the left side we have a table view inside a navigation controller at the root of the app. The detail view controller has a push segue from the prototype cell’s disclosure indicator and a modal segue from the plus button at the top right of the root view controller.
We want to have a “Cancel” and a “Save” button for both modes, mostly for the sake of this demonstration. When creating the sample app I found that there is a scenario where Interface builder would only allow me to add a single button to the detail view controller’s navigationItem. I had to delete it and add a new view controller, connect it to the navigation controller as root view and then I was able to drag two buttons to the navigation bar.
In the implementation for the root view controller add the following code:
// here we get back from both styles - (IBAction)unwindFromDetailViewController:(UIStoryboardSegue *)segue { // UIViewController *detailViewController = [segue sourceViewController]; NSLog(@"%@", segue.identifier); } |
The key is that you place a method with this signature into a view controller you want to unwind to. That is different from regular IBAction methods which you would put in the same view controller that has the controls. This also is the reason why many people don’t know that this feature even exist.
Now go back to the storyboard editor, select the detail view controller and Ctrl+Drag a blue line from the bar button items inside the navigation item down to the green Exit symbol.
When you let go you are presented with a list of unwind segues. Xcode finds possible targets from looking at your implementations and searching for methods that have the appropriate signature. Pick the one you want to unwind to when this button is clicked. It doesn’t have to be the one before it. You can even unwind multiple levels down.
For each such connection to an Exit a new Unwind segue appears below. In order to tell them apart you should give them identifiers. Those allow you to determine whether it was the Cancel or Save button that triggered the unwind. Alternatively you could also have separate unwind methods – as shown above – for cancel and save.
And you’re done!
Savor for a moment the feeling of never having to write something like dismissViewController and/or having to check if the view controller was presented modally or by push. The unwind segues are smart enough to know the correct way how to get back to the view controller you want to unwind to.
The example app I made for this tutorial is on my Examples GitHub repo.
Conclusion
There are additional methods to further customize unwinding behavior, especially for supporting it in code. But you usually don’t need to care about these. The key takeaways are:
- The unwind method goes into the view controller you want to end up at.
- Connecting to the Exit symbol will work only after you have defined such a method.
- Ctrl+Drag from a control to the Exit symbol to select the unwind segue you want this control to perform.
- Unwind segues appear below the Exit symbol for each connection made.
- You can give those unwind segues an identifier to have different activities performed.
When building storyboard-based apps the knowledge how to employ unwind segues will save you a lot of boilerplate code.
Categories: Recipes
This post came exactly when I needed it for my app! You never cease to deliver! (:
can you use prepare for segue to do some clean up before the view unwinds?
Thank you. what code do you use to unwind with a custom segue?