A storyboard allows me to setup a nested navigation controller with a push segue (and it works fine):
But if I try and do it without a segue in code, I (expectedly) throw an error:
'Pushing a navigation controller is not supported'
#IBAction func showTapped(_ sender: Any) {
guard let secondNav = self.storyboard?.instantiateViewController(withIdentifier: "SecondNavID") else { return }
self.navigationController?.pushViewController(secondNav, animated: true)
}
Ultimately, I'm trying to reproduce the above storyboard behavior in code (without a segue), but I'm not sure what it's doing.
Is the storyboard defaulting to "present" even though it's set it to "show"?
Although a storyboard may seem to permit nested nav controllers, that configuration is illegal outside a collapsed split view controller and should never be used (according to Apple).
Here is a screen grab of both a "Show" and a "Present Modal" so this seems to be the case that the storyboard is just reverting back to a Present for a navigation controller:
https://imgur.com/a/7ytObW2
It seems as if the best solution is to remove any "Show" segues and replace with "Present"
As a workaround, you could present the navigation controller instead of pushing, therefore you will should have the hierarchy as:
Nav Controller embeds view controller => presents Nav Controller embeds view controller.
Related
i have multiple storyboard in my storyboard. I have embedded the firstVC with navigationcontroller and remaining attached to the firstvc through segues. The remaining VC's are not embedded in navigationcontroller. Now when i click the button to open the next VC without navigation controller. It opens it twice. When i disconnect the segue it does not open the VC. I'm confused that why this is happening so. This is how my UI Looks,
This is how i perform the segue,
self.performSegue(withIdentifier: "GoToNextVC", sender: self)
View Controllers operate on a stack hierarchy. By embedding your first view controller in a UINavigationController and setting that as the Initial View Controller, you're making it the root view controller for the whole stack. The issue you are experiencing is occurring because you are segueing to view controllers without the root view controller's knowledge every time you call performSegue(withIdentifier:sender:). This causes the stack to be out of order and disjointed, preventing you from returning to the previous view controller(s) when calling dismiss(animated:completion:).
Instead of segues, try pushing each view controller to the stack with:
navigationController?.pushViewController(VIEW_CONTROLLER, animated: true)
To use this:
Remove any segues in Interface Builder, they are no longer needed.
Replace VIEW_CONTROLLER with the view controller you want to push.
I'm trying to adding a navigation controller and to associate it with the home (and of course the controllers that are connected to the home)
this because i prefer to not have the navigation controller in the first 3 VC (storyboard entry, login and sign up). My problem is that after a simple self.performSegue(withIdentifier: "goToHome1", sender: self) from one of the first three VC the navigation bar disappear, is the first time i'm going to add a navigation controller and until now i always used only this formulaself.performSegue(withIdentifier: "goToXcontroller", sender: self) to switch from one controller to another so maybe i have to change something to fix this problem? I also tried to find some tutorial about NC but i didn't find something clear that help me with this.
You have to create segue to your UINavigationController instead of home view controller. You are skipping navigation controller by directly using segue to home view controller.
Rootviewcontroller of your navigation controller is Home view controller. So if you create a segue to your navigation controller, it will open your home view controller with navigation bar.
I'm a swift newbie and I've got a simple question which I hope someone can help me figure out.
I have a multi-tab app. I created some segues from the tab view controllers on the Stopryboard. I've given the segues identifiers and I'm calling them from my Tab1ViewController code using performSegueWithIdentifier("tab1ToMyTarget", sender: sender) no problem.
However, I'd like to be able to call the segue from any of the app's tabs without creating new segues from the other tabs' view controllers (i.e. I don't want to create "tab2ToMyTarget" - I presume there's a better way!).
My question: Do I create these 'universal' segues on the tab bar view controller (e.g. "tabBarToTarget") (and if so how do I call it from one of my tab view controllers)? ...or...
Do I keep the segue from a single tab view controller (tab1ToTarget) and call that segue from a sibling tab view controller somehow?
First, set the view controller that you want to go to's storyboard Id. Then run this:
let vc = storyboard!.instantiateViewControllerWithIdentifier("someViewController")
self.presentViewController(vc, animated: true, completion: nil)
You cannot use the same segue to open a controller from a different one. It's better to instantiate a view controller with its storyboard id and then present/show based on the flow.
So I have two navigation controller hierarchies that both lead to one view controller. I pass that one view controller data based on which one presented it with a push segue. How do I dismiss the final view controller and go back to the navigation stack that presented it? I don't need to pass any info back, but when I tried to do an unwind segue I was getting an error stating "this class is not key value coding-compliant for the key doneButtonTapped" I tried unWind segue and popVC segue.
I believe the problem might be that you can't have two separated navigation stacks leading to one view controller because that view controller doesn't know which stack it is a part of. I tried researching but could only find how to dismiss multiple modal views at once, nothing about dismissing one VC to which ever VC presented it at the time.
Thanks
You just need to call popViewController to dissmiss viewcontroller. It will automatically follow navigation stack which was created by navigationcontroller A or B.
If you want to pop to first viewcontroler then can call popToRootViewController.
Hope this will help :)
Just set storyboard ID's for the navigation controllers, Once you reach the final view controller. Just use:
self.performSegueWithIdentifier(identifier: String, sender: AnyObject?)
use prepareForSegue to get to NavigationViewController you want
Set a Bool value and pass it along from Navigation view controllers, while traversing to the last view controller. For example, pass true when going from Nav A, and pass false when going from Nav B. Once you get to the final ViewController, use this boolean value :
if boolValue == true {
self.performSegueWithIdentifier(identifier: "identifierforNavA", sender: AnyObject?)
}
else {
self.performSegueWithIdentifier(identifier: "identifierforNavB", sender: AnyObject?)
}
Don't forget to implement prepareForSegue for performSegueWihIdentifier to work
Since I can't find anything about this case, I guess I'm doing something wrong, but not sure why.
I have:
NavigationController -> (root view) UIViewController (1st) -> (here is a segue) -> UITabBarController (2nd) -> UIViewController
I want to make segue from 1st UIView to 2nd UIView while pushing 2nd into Navigation Controller stack.
When I'm doing pushViewController inside prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mySegue") {
self.navigationController?.pushViewController(segue.destinationViewController, animated: true)
}
}
I've got exception
Application tried to present modally an active controller
(which is obvious, because I made push with nav controller and then segue trying to present the same view again)
How can I use a segue with Navigation Controller at the same time?
Thanks!
UPD. As noted in answers, deprecated Segue type "Push" (not a "Show (e.g. Push)") works exactly as I want, but it's deprecated... Is there any "good" way?
If you're using storyboards to setup the segues, you just the segue type to 'Push' and it will push it from the nearest UINavigationController ancestor. You just need to call self.performSegueWithIdentifier("yourSegueIdentifierHere") and the Navigation Controller will push it.
After you call this, the Current View Controller will call prepareForSegue to set up the next View Controller to be presented. You are getting the error because you are trying to get the navigation controller to push the same view controller that is already trying to be presented.
Hope this helps a bit.