Whats the difference between moving between Storyboard scenes - Segues and Unwind - ios

I'm a fresher. I used segue to go (Flow of Execution) such like that
UIViewController A => UIViewController B => UIViewController C.
And used unwind segue to move from C to A. But I am confused about how they different of each other.
And Why I use unwind segue although I have delegation.
Thank You in advance.

Regular Segue allows us to send data from one view controller to another, but it’s not easy to bring data back if the user has changed or added details in that view controller. That’s where an Unwind Segue comes in.
Read more here

Segues are for presenting a new view controller.
Unwind Segue is a special kind of segue (A go back mechanism) which moves back to the connected destination.
A->B->C->A
If you are using segue for above mentioned flow, there will be two different instance of A in the memory.
If you use unwind segue for the C->A transition
It act as a go back mechanism and it removes the C and B instance from the memory once the segue is over
There will be only 1 instance of A

Related

Is it possible to use an unwind segue from a single modal view controller back to one of multiple instances of the same source view controller?

My Storyboard layout is such that I have MainVC connected to ModalVC via a segue that presents it modally.
However, programmatically, at runtime, I instantiate five instances of MainVC in total.
As a result, all five instances of MainVC, with the same identifier, are connected to ModalVC.
I need to change properties in MainVC after performing some actions in ModalVC and dismissing it, and there appear to be various ways to do this via segues.
The top answer here is quite detailed and explains the implementation of using an unwind segue but only in the scenario of there being one source view controller:
Passing data with unwind segue
My question is: will using a segue, like in that answer, or any other way, work in my situation, with multiple instances of the same MainVC (same identifier) attached to a single instance of ModalVC?
Will the unwind segue only transfer data or perform actions in the single MainVC instance that initiated it? Or will it end up affecting all five MainVC instances because the MainVC instances have the same identifiers? If the latter, is there any way around this?
Apple has a comprehensive technical note on how unwind segues work and how the destination view controller is determined, but, in summary, the process examines the view controller navigation hierarchy to find the first view controller that can handle the unwind segue and is willing to do so.
In your case, this would be the MainVC instance that presented the ModalVC that is unwinding. The unwind segue cannot be handled by a view controller instance that is not in the navigation hierarchy (e.g. An instance of MainVC that did not present the ModalVC)

iOS Storyboard - Switch View to another view controller at same hierarchical level

If I have a storyboard that contains 3 views - a root, and two 'child' views that the root view can segue to. Is it possible for the children to segue to the other child, and then when its complete, return back to the root?
In my case, the root view may segue to view 'A' or 'B' depending on some event. However, its possible that some event in 'A' may require view 'B' to be displayed, and when its done it should return back to root. i.e., the steps of naviation would be: Root -> ChildA -> ChildB -> Root.
Currently, I have the app setup to unwind from ChildA back to root, and have it then display 'B'. Two issues arose from this method:
Unable to segue to a new view when the unwind segue is still in operation. I had to hack around this, and currently have a performSegueWithIdentifier being called with a small delay to get around it. Obviously a bad hack.
The root view controller is displayed for a moment until the new segue starts & completes.
I figured I could have A segue to B, but then when B was done, the unwind operation that I want to go back to root would have to unwind two items on the view stack??
I'm sure there has to be an obvious design choice that handles this type of thing right?
I figured I could have A segue to B, but then when B was done, the unwind operation that I want to go back to root would have to unwind two items on the view stack??
Unwind operations are not required. In your case, it might be better to have A segue to B, and when B is done, segue to root. No unwind required.
If, however, you want to stick with unwinding, Craig Phares posts how to perform multiple unwind animations without showing intermediate controllers (i.e. you would pop right back to root).
Hope this helps!
First, I believe you mean "view controller", right?
If that's the case, there are many ways you could navigate from A to B. However, it seems like you're using the NavigationController in an unusual way.
For example, is it necessary to have a segue from the root to B? If not, then maybe you should create a single segue from A to B and, when you're at B, you can use "popToRootViewController" to go back.
Or maybe you could present B modally instead of having a "show"/"push" segue to it. In that case, you would have to go back to A before going to the root.
Anyway, once you're at ViewController B, you can popToRootViewController and you'll get back to your root.

How to unwind segue several steps back?

There are a lot of stuff on the net according the topic but I don't get it. I have an App with Custom segue implementation and without Navigation controller. There are cases in which I need to unwind back several steps.
For implementation I use simple calls:
CODE CUSTOM SEGUE
For wind:
[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:YES];
For unwind:
[[self destinationViewController] dismissViewControllerAnimated: YES completion: nil];
As I understand when I wind segue somewhere in the memory there is data which is used during the unwind. For that reason in the custom unwind I only use read only property destinationViewController.
So how can I unwind several steps back in one action? Or I have to make several unwinds in different View controllers?
I read the following question, but I don't understand implementation.
Bellow I put example of my apps logic:
EXAMPLE
I have 4 VC which is in a chain:
VC A -> VC B -> VC C -> VC D
I wind and unwind back and forth. The logic is ok. There are situation in which I need to unwind back from VC D to VC B. How to do that? Can I unwind directly to VC B or I have to unwind to VC C and then in the unwind handler to unwind to VC B?
I also thought of additional segue from VC D to VC B, but there are remarks on the net that this is not the right way, because segue chain will get messy.
The answer to What are Unwind segues for and how do you use them? has everything you need to know about unwindSegues (I suggest you re-read it).
But for a more direct answer, yes you can unwind back from VC D to VC B. To do that you have to first implement the method in VC B:
- (IBAction)unwindToVCB:(UIStoryboardSegue *)unwindSegue
{
}
after doing so, go to the IB, and control-drag a button's action to the Exit icon, you should then pick the method you created above as the selector. (This is taken directly from the question/answer stated above).
Again, for a clearer version of what I said, read the answer of the linked question I mentioned above.
You have to use UINavigationController, just add it in storyboard as mainViewController and set 'A' ViewController as root view controller for it, then change all segues to push segue, set 'Identifires' for them, and you can use performSegueWithIdentifire to push view controller and inside view controller:
[self.navigationController popViewControllerAnimated:];
or
[self.navigationController popToViewController: animated:];
to dismiss it.

Can I send performSegueWithIdentifier: to anything other than self?

I have a category on UIViewController that deals with errors coming from my networking layer. If I get an authentication error in response to a network call, I want to perform an unwind segue which takes me back to my LoginViewController.
However, I don't want to have to add the appropriate unwind segue to every single view controller in my Storyboard. Can I simply declare the unwind segue in the UITabBarController that is at the "top" of my view controller navigation, and then say
[self.tabBarController performSegueWithIdentifier:#"UnwindToLoginSegueIdentifier" sender:self]
... from inside my UIViewController+ErrorHandling category?
No, you can't do that. The unwind segue has to come from the controller you're unwinding from, and all segues need to be connected from a particular instance in the storyboard. The login view controller really should be one that's presented modally, not be one of the tabs, since you only need it briefly, then it should go away. If you set up your app that way, you can present and dismiss it from any controller (present it without animation from the controller in the first tab, if that's what you want the user to see when the app launches). You'll still have to have code in every controller to do that, unless you make a common base controller with that functionality that all the other controllers inherit from.

My Navigation Controller Count Keeps Growing

I'm new to iOS dev and am not entirely sure on Storyboards/Segues/Pushing and Popping.
So in my app I have a navigation controller with 5 view controllers leading from one to another.
When it reaches the last view controller i have a segue to the first and I have a few tasks listed in the prepareForSegue method.
Out of curiosity I decided to check what happens to the [self.navigationController.viewControllers count]. I found that it keeps growing and growing which doesn't 'feel' correct.
Am i handling going back to the first screen correctly? The prepareForSegue method is useful as it allows me to send some data back to the first segue. Is it possible to maybe say when you go back clear all views on that navigation controller?
Thanks
You can use an unwind segue. Here's a good tutorial:
pragmaticstudio.com/blog/2013/2/5/unwind-segues
Make sure to create the unwind action method before you wire it up in the storyboard otherwise it won't show up when you drag to 'Exit'. That was the most confusing part for me when I first set one up. The tutorial does it in the correct order so if you follow it you should be fine.
Also, here's a sample I put together showing how to transfer data back in an unwind segue. It uses a modally presented view controller but the technique is the same:
github.com/soleares/AddToTableView
No, you should never go backwards with a segue (other than an unwind). Segues ALWAYS instantiate new controllers, so you're not actually going back to the first controller, you're just creating a new instance, which gets added to the stack. So either go back with an unwind segue or use popToViewController:animated:. Using an unwind segue will allow you to use prepareForSegue, and it does cause all the controllers in between to be deallocated (if you have no other strong pointers to them).

Resources