When my child performs an unwind segue, my controller's viewDidAppear gets called.
In this method (and this method alone, I need to know whether it was from an unwind or not)
Note: the child is unwinding to the very first view controller, so this is an intermediate view controller, not the true root.
Suppose the segue navigation is ViewController -> FirstViewController -> SecondViewController. There is an unwind from
SecondViewController
toViewController
. You can add in the intermediaryFirstViewController
the following code to detect unwind actions.EDIT After giving this some thought, I decided the solution to this depends on the kind of complexity that you are dealing with here. What exactly do you do when you do the unwind segue? The solutions given here are viable and they work -- only if you want to detect whether it is an unwind action. What if you want to pass the data between the point where the unwind is happening to the root? What if there is a complex set of preparations that you wanna do in one of the intermediate view controllers? What if you want to do both of these?
In such complex scenarios, I would immediately rule out overriding the unwind methods of the view controller. Doing such operations there will work, but it won't be clean. A method will be doing what it isn't supposed to do. Smell that? That's code smell.
What if, somehow a view controller could inform the next view controller in the hierarchy of the event happening? Better yet, how do we do this without tightly coupling these two?
Protocol.
Have a protocol definition something like:
Using protocol you will keep the relationship between the objects -- the hierarchy of view controllers in this case -- explicit. At the point of occurrence of a particular event, you will delegate the call to the next controller in the hierarchy informing about the happening of a particular event in another view controller. Here is an example:
In the intermediary view controller you can do something like:
Granted, you wouldn't wanna do this if you just want to detect unwind segues. Maybe you do, you'll never know what will happen in the future. Never hurts to keep your code clean.
You should be able to use the following to detect in each controller if the exposure of the view controller was as a result of being pushed/presented, or as a result of being exposed as a result of pop/dismiss/unwind.
This may or may be enough for your needs.
If you want to know that
viewDidAppear
was called because of an unwind segue as being different from a conventional pop/dismiss being called, then you need to add some code to detect that an unwind happened. To do this you could do the following:For any intermediate controller you want to detect purely an unwind in, add a property of the form:
Then override the unwind segue method
canPerformUnwindSegueAction:fromViewController:withSender:
method as follows:Now you have a flag to detect an unwind and a means to detect the unwind just before it happens. Then adjust the
viewDidAppear
method to include this flag.Hopefully this meets your requirement.
For docs on handling the unwind segue chain see: https://developer.apple.com/library/ios/technotes/tn2298/_index.html
Add method in your parent view controller
As an exemple if the unwind segue is related to a button, in the storyboard link your button to it's view controller exit
It will propose to link to unwindToParent method
Then each time the unwind segue is performed, the
unwindToParent
method will be calledfor anyone else looking for this, in swift you can use the override function "unwind", this is called when the ViewController is on the path of an unwind segue, meant to reconfigure the ViewController.
example:
Here is a simple category on UIViewController that you can use to track whether your presented view controller is in the midst of an unwind segue. I suppose it could be flushed out more but I believe this much works for your case.
To use it you need to register the unwind segue from your unwind action method on the destination view controller:
That's it. From your intermediate view controller, you can test if you are in the midst of an unwind segue:
There's no need to clean anything up; the segue will self-deregister when it ends.
Here's the full category:
Your question was really interesting to me, because I never used IB and segues before (don't judge me for that) and wanted to learn something new. As you described in your comments:
So I come up with an easy custom solution to this:
You also could modify the callback function to return something else, like controller identifier instead the controller itself.
I do everything programmatically, so please don't judge me for that too. ;)
If this code snippet won't help you, I'd still love to see some feedback.