Reputation: 1356
I have set up a NavigationController programmatically in my SceneDelegate. My app logic requires at a certain stage to go back to a specific ViewController on the stack. The problem is that when I do this with popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]?
, I seem to loose track of the NavigationController – there is no Back button available even though I did not pop back to the root controller.
When I am in the ViewController in question, my NavigationController's ViewControllers' stack looks like this:
(lldb) po navigationController?.viewControllers
▿ Optional<Array<UIViewController>>
▿ some : 4 elements
▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>
▿ 2 : <Vocabulary.LearnViewController: 0x7fbd45532180>
▿ 3 : <Vocabulary.LearnResultViewController: 0x7fbd4569f900>
(lldb) po mainNavigationController.viewControllers
▿ 4 elements
▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>
▿ 2 : <Vocabulary.LearnViewController: 0x7fbd45532180>
▿ 3 : <Vocabulary.LearnResultViewController: 0x7fbd4569f900>
I now pop back to navigationController.viewControllers[1]
in LearnResultViewController
like so:
override func willMove(toParent parent: UIViewController?) {
if let _ = mainNavigationController.topViewController?.isKind(of: LearnResultViewController.self) {
if isPresenting {
if let vocabularyViewController = mainNavigationController.viewControllers.first(where: { $0 is VocabularyViewController} ) {
mainNavigationController.popToViewController(vocabularyViewController, animated: true)
//navigationController?.popToViewController(vocabularyViewController, animated: true) //same behavior
}
}
}
}
isPresenting
is just a flag I set in LearnViewController
in viewDidLoad
cause willMove
is called when entering LearnViewController
already and obviously I only want to pop when leaving and mainNavigationController
is a global variable right now (mainly cause I thought it should be global so that it can be referenced from anywhere which did not help so far...).
Now when I do hit the back button, I can get back to VocabularyViewController
, but I don't have a Back button any more there – so the stack of my NavigationController seem to be lost.
While still in willMove
I can see that LearnResultViewController.navigationController
becomes nil
– which causes my problem. Above mentioned mainNavigationController
still has the state by then, but the "local" navigationController becomes
nil:
(lldb) po mainNavigationController.viewControllers
▿ 2 elements
▿ 0 : <Vocabulary.MainViewController: 0x7fbd4570dcd0>
▿ 1 : <Vocabulary.VocabularyViewController: 0x7fbd4566ce80>
(lldb) po navigationController?.viewControllers
nil
(lldb) po navigationController
nil
What can I do to just get back to the desired ViewController while keeping my stack / state in my NavigationController? Is there another approach I should take?
To be quite frank I don't even understand why the scene's navigationController is set to nil in the first place...
Upvotes: 1
Views: 619
Reputation: 587
I tried your approach, and it really doesn't work.
You should remove LearnViewController from your navigation stack in LearnResultViewController.
navigationController?.viewControllers.removeAll(where: { $0 is LearnViewController })
After that, when you hit the back button, you will get back to VocabularyViewController. And the back button will be there.
You shouldn't override willMove for that.
Upvotes: 1
Reputation: 3859
for swift 4.0
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: DashboardVC.self) {
_ = self.navigationController!.popToViewController(controller, animated: true)
break
}
}
for swift 3
let viewControllers: [UIViewController] = self.navigationController!.viewControllers
for aViewController in viewControllers {
if aViewController is YourViewController {
self.navigationController!.popToViewController(aViewController, animated: true)
}
}
Upvotes: 1