I want to push my Navigation Controller but I get :
pushing a navigation controller is not supported
I can't instantiate my TableView.
This is my code :
let newViewController = storyboard!.instantiateViewController(withIdentifier: "player") as! UINavigationController
self.navigationController?.pushViewController(newViewController, animated: true)
So there is a way to push the NavigationController ?
Here we can see the first line means that is the stack of view controller to provide drill down, So you have to push minimum one UIViewController object in the stack or make the root of the stack to any view controller for navigation controller.
From apple document.
A navigation controller manages a stack of view controllers to provide
a drill-down interface for hierarchical content. The view hierarchy of
a navigation controller is self contained. It is composed of views
that the navigation controller manages directly and views that are
managed by content view controllers you provide. Each content view
controller manages a distinct view hierarchy, and the navigation
controller coordinates the navigation between these view hierarchies.
Read this
Set your tableVC as root view controller of navigation controller :
let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var tableViewController = mainStoryboard.instantiateViewControllerWithIdentifier("TableViewController") as! HomeViewController
let navigationVC = UINavigationController(rootViewController: tableViewController)
appdelegate.window!.rootViewController = navigationVC
Now in TableViewController ,to hide navigation bar
self.navigationController?.setNavigationBarHidden(true, animated: false)
Then you can push another view controller like you mentioned
let newViewController = storyboard!.instantiateViewController(withIdentifier: "player") as! UINavigationController
self.navigationController?.pushViewController(newViewController, animated: true)
Related
I've separated my views into multiple storyboards to make managing the project as a team much easier. The only problem is that I want to have the navigation bar across all of my different view controllers. I embedded the first view controller in a navigation controller which added the navigation bar. In my second storyboard, I wanted to constrain a view to the navigation bar, however, since this view controller isn't embedded in a navigation controller, there isn't anything to constrain the view to. I put a navigation bar without a navigation controller to constrain to, however, when I perform the segue from the first storyboard, this results in two navigation bars. How do I make this so that I can constrain the view to the navigation bar without having two of them? Thanks in advance!
You can go from on view controller to another by three way:-
First using segue as you are already doing
second You can Present your view controller by
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController")
self.present(controller, animated: true, completion: nil)
Third You can Navigate View controller by
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController")
self.navigationController?.pushViewController(controller, animated: true)
I'm not sure your problem. I guess that you want to use ONE navigation bar to constrain many UIViewController in different Storyboard. Here is my answer.
Step 1: Set up Storyboard ID in each UIViewController
Step 2: push new UIViewController
func switchNextView() {
let storyboardName:String = "xxxxxx"
let storyboardId:String = "xxxxx"
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
let vc: UIViewController =
storyboard.instantiateViewController(withIdentifier: storyboardId) as!
UIViewController
self.navigationController?.pushViewController(vc, animated: true)
}
I am using navigationController?.popToRootViewController(animated: true) to dismiss my current view to the previous view. My view controller relationship looks like this.
VC1->VC2
VC1->VC3
VC3->VC2
Whenever the client is in VC2 I want to pop the navigation controller back to VC1. This works fine when the rootviewcontroller is set to VC1. However, when the client uses a segue from VC3 to enter VC2, the rootviewcontroller is set to VC3 and the navigation controller pops to VC3.
I tried to change the rootviewcontroller like this.
// set root view controller
let appdelegate = UIApplication.shared.delegate as! AppDelegate
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let VC1 = mainStoryboard.instantiateViewController(withIdentifier: "VC1") as! FirstViewController
appdelegate.window!.rootViewController = VC1
navigationController?.popToRootViewController(animated: true)
But this actually returns the viewcontroller to the root view controller (VC1) even before the line "navigationController?.popToRootViewController(animated: true)" is executed so there is no animation.
Is there any way to set the rootviewcontroller of a navigation controller without presenting the root view controller right away?
If you put appdelegate.window!.rootViewController = VC1, the stack of controllers has died, you only have in the stack an alone Controller, therefore you can't apply popToRootViewController.
If this is your required navigation, maybe, this post helps you:
I have an application with 5 tabs(and a UITabBarController). I have more view controllers which can be shown when user clicks buttons etc. Right now I'm trying to push a view controller in the first tab. When I use the following code, the new view controller completely replaces both the tab bar and the previous view controller so the only view controller that is shown is the new one and there's no way to go back. Here's my code:
#objc func openSettingsPage() {
let vc = UIStoryboard(name: "SettingsPage", bundle: nil).instantiateViewController(withIdentifier: "Settings") as! SettingsViewController
self.tabBarController?.show(vc, sender: self)
}
I've also tried:
let vc = UIStoryboard(name: "SettingsPage", bundle: nil).instantiateViewController(withIdentifier: "Settings") as! SettingsViewController
self.navigationController?.pushViewController(vc, animated: true)
Nothing happens when doing that. trying print(self.navigationcontroller) prints "nil" so apparently it doesn't find a navigation controller even though the view controller I'm writing the code in is embedded in a navigation controller
I've got this view hierarchy in my app.
Tab bar => item 1 is collection view embedded in a navigation controller.
Item 2 is a split view controller
The split view controller => master (table view controller) embedded in a navigation controller.
Detail (table view controller [the target]) embedded in a navigation controller and has a child table view controller
Based on receiving push notifications, I would like to show [the target] table view controller that is way above in the view hierarchy (as depicted in the image) and still keep the same view structure/ hierarchy so that a user may still navigate throughout the app. So the trick of
window?.rootViewController = targetViewController is no good.
I've added the below code but it crashes the app with error 'Tried to pop to a view controller that doesn't exist.'
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let targetController = storyboard.instantiateViewControllerWithIdentifier("targetController") as! TargetTableViewController
let tabBarController = window!.rootViewController as! UITabBarController
let splitController = tabBarController.viewControllers!.last as! UISplitViewController
let navController2 = splitController.viewControllers.last as! UINavigationController
navController2.popToViewController(targetController, animated: true)
In my app I am making the account page the new root VC when a user logs in.
It looks like this:
Navigation controller -> table view -> menu(modal segue) -> login screen(modal segue) -> account page
When transitioning from login to account I am using:
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let vc = storyboard.instantiateViewControllerWithIdentifier("testVc")
let navigationController = self.view.window?.rootViewController as! UINavigationController
navigationController.setViewControllers([vc], animated: true)
This makes the account page the new root VC. But the only problem is that once is shows up both the menu and login form is still visible ontop of the screen.
So how do I clear two old VC's shown as modal?
Update got it to work using:
#IBAction func loginButtonDidTouch(sender: AnyObject) {
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("testVc")
let navigationController = self.view.window?.rootViewController as! UINavigationController
self.presentingViewController!.presentingViewController!.dismissViewControllerAnimated(false) { () -> Void in
navigationController.setViewControllers([vc], animated: true)
}
}
But I dont know if this is the right way to do it?
You need to get the reference of those controllers, and then dismissing them.
Try this:
let loginScreen = self.window.rootViewController.presentedViewController
loginScreen.dismissViewControllerAnimated(false) { () -> Void in
let menuScreen = self.window.rootViewController.presentedViewController
menuScreen.dismissViewControllerAnimated(false, completion: nil)
}
When you're calling the original navigation stack and modifying it:
let navigationController = self.view.window?.rootViewController as! UINavigationController
You are setting the new view controller (#testVc) by replacing the only other view controller, "tableview", in that navigation stack.
The modally presented views are not a part of that particular navigation stack and instead are presented above the current navigation stack as new stacks (this gives you a pointer to the new Navigation Controller on top in the form of self.navigationController to push new views)
You can explicitly dismiss the two modally presented views by calling dismissViewControllerAnimated(_:completion:) on each, most likely by propagating the communication through a delegate response or through the completion handler.