Back to correct view controller - ios

I have three view controllers A, B and C.
C is the target.
From A, I have a segue named showCFromA to view controller C.
From B, I have another segue named showCFromB to view controller C.
Now, when C is displayed (shown from B), I tap on the "Back" button, but at this stage, it shows A, and not B as I expected.
How can I fix that?

Don't mess with Back - it makes for a disjointed app experience. You end up at a place you don't expect to be and navigation just doesn't feel right.
If you have a B on the stack, you can just
popToViewController:animated:
to return to the specific view controller (B) that you want to see.
If you have gone from A directly to C with no intervening stop at B, you can't go there with back. Instead you should just push a B.
If your B should be on the stack - i.e. you went from B to C - then B is where you should end up if you simply go back. If that is currently not the case you need to post some more details to help diagnose the problem.
What is confusing right now is what you actually have on the stack. You mention being at A and going to C, then being at B and going to C, but the order in which you do this (and if these are two separate cases) affects the outcome.

After checking the source again, I found the issue is not properly handling navigation vc stack. When push new VC from B, when viewWillDisapper is called (B), I added "popViewController". Therefore, navigation view controller array has count of 2 (the middle element is removed). This makes strange behavior: From view controller C, I cannot go back.

Related

How do I return to my primary display (A) if I go from screen A to B to C back to B using unwindSegue

I currently am learning how to program in Swift and have made 3 different pages; Pages A, B, and C. From page A, I am able to navigate to page B, and from page B, I am able to go to either page C or page A. When I go to page C I can go back to page B or page A.
The issue that I am running into however is that if I go from Page A to Page B to Page C back to Page B, when I try to close Page B, it would display Page C briefly before closing back to page A.
All of these are on separate viewcontrollers and I've just been presenting all of them modally each time
I've tried using Unwind Segues Step-by-Step and Create Unwind Segues in Swift 3
to understand what I've been doing wrong, however from what I've read on them (and from my limited knowledge of Swift), none of them discuss going back a single page and then trying to close after. They all go from 1 -> 2 -> 3 back to 1 without the intermediate step of going back to page 2.
#IBAction func close (_ unwindSegue: UIStoryboardSegue){} is what I've been using as my unwindSegues linking these up to my Exit placeholder. This was done on both Pages B and C
Currently there is no error message, it appears to work but it does show that intermediate screen which is not what I am looking for.
Thanks!
You said:
when I tap on the back button on page C -> B it shows that I trigger an Action that presents Modally (if that helps)
That is precisely the problem. Having gone from A to B to C, C should not then modally present B again. You’re creating a new, second instance of B. You’d have a view controller hierarchy that looks like:
A » B1 » C » B2
If, though, you successfully dismissed/unwound from C to B, you would have ended up with only A and B in the view controller hierarchy:
A » B
And then, when B went to dismiss/unwind to A, C would be long gone and there’s no way you’d see it in your animation.
If you’re using unwind segues, I’d suggest that view controller A had an unwind action like so:
#IBAction func unwindToA(_ segue: UIStoryboardSegue) { }
And view controller B could have an unwind action like so:
#IBAction func unwindToB(_ segue: UIStoryboardSegue) { }
Now, when C wants to unwind back to B, if you could use the latter unwind action. If you want to unwind to A (either from B or C), you could use the former one.
Just make sure that you never present/show when you want to go backwards in the view controller hierarchy. Either use unwind segues, or dismiss/pop as appropriate.
I don't really understand your question. But I guess your problem is you used present instead of dismiss when you back to B from C.
Sorry, your question is not fully clear to me . So far I understand if you wanna back from C to B View Controller , then you can do it Simply use
self.dismiss(animated: false, completion: nil)
in Your Exit Button action . Hopefully it will help .
Seems quite confusing question description.
Not sure but maybe you have mistakenly added segue from Page B -> C on the same Back button. Please check that also.
I've created SimpleUnwindExample project on GitHub. Hope It will help in to fix your issue.
Repository Link: https://github.com/harshal-wani/SimpleUnwindExample
Cheers!

Data passed through segue lost after hitting back button

I have two view controllers A and B and a segue from A to B (type: show) through a next button and a segue from B to A (type: show) through back button. I am passing some data through segue A to B. Data is displayed correctly if I just tap next from controller A and go to controller B.
However, If I tap next and go to controller B and hit back and come back to A and then hit next again, it doesn't work. Any ideas whats going on here? Sorry for the confusing language.
Sounds like your "B to A" is wrong, you're using a navigation stack so you should only push (show) when you are moving forwards. When going backwards you should pop off the top (dismiss)
If you keep pushing, the app will continue to just put more and more ViewControllers in memory, which is bad.
I suspect whats happening here is View A initially has the data and passes it to View B. Then when you press your back button it creates a new copy of View A which doesn't have the data and shows that instead of the original View A.
In Short: (A to B :type - show) (B to A :dismiss the current ViewController)
I agree with user2877496 in that you should not use a regular segue to go back from B to A as you will be adding "A" onto the stack each time.
I just wished to add that one method to dismiss B and go back to A is by using an Unwind Segue.
The Apple documentation covers this quite well
https://developer.apple.com/library/content/technotes/tn2298/_index.html
Did you resolve this? My guess is you put stuff to execute in viewDidLoad (which only runs once at the start of your app) and it needs to be in viewWillAppear so it is called each time you return to your main view controller. Please provide your code for those methods if you require further help.

Dismissing multiple view controllers at once with strange behaviour

This is a common problem and for everybody who still doesn't know the correct way how to deal with that, here is the scenario.
Modally presented view controllers A -> B -> C
Now you want to dismiss C with B at one smooth animation landing to view controller A. So apple documentation says that you only need to perform:
[A dismissViewConttollerAnimated:YES completion:nil];
And C with B should be nicely gone. This is really often needed scenario and I'm really said and disappointed that the common use case is not working properly. Why the top view controller C disappears in a moment and B view controller appears with dismissing animation instead of C to be visible for the whole animation process? I would really except to see only C view controller's dismission.
The best solution to use in this case is Unwind Segue. You can directly move switch to any view controller in the heirarchy.
The dismissal of B can't be done in parallel with dismissal of C. This happens sometimes in iOS when the two animations are related somehow - I don't know the exact details.
If you put a breakpoint in C's dismissal completion block, you'll probably see the finished parameter being false, indicating C's animation has been interrupted.
I think the correct solution is to dismiss B only. C will be gone automatically since it was presented by B.

How Remove middle UIViewController from presentation stack

I am an experienced iOS developer, but I've stumbled upon an issue that I'm not entirely sure how to solve.
Lets say for example I have 3 UIViewControllers, A, B, and C respectively. A is the root and B is presented on top of A and C is presented on top of B.
B and C are presented using presentViewController:animated:completion:
So the presentation stack looks like this.
[A] -> [B] -> [C]
In my program, I want to dismiss B and only B. The docs for
dismissViewControllerAnimated:completion: says that if I dismiss B, it will ask its A to dismiss B and then will also dismiss C as well. I do not want that. I want to dismiss B only such that A will choose C as its presentedViewController like so
[A] -> [C]
Is this possible?
--------Notes-------
I realize that this seems more suited for another presentation pattern where A,B,C would be siblings under a common parentViewController. But I May not use that.
The presentedViewController/presentingViewController pattern is just like a doublylinked list. However, since these properties are read-only, I can not do any node manipulation.
Could you use a navigation controller with the navigation bar hidden and push the controllers rather than present them (using a push and pop animation that mimics that of presentation).
Then use setViewControllers to replace the ABC stack with an AC stack?

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.

Resources