This question already has answers here:
Set rootViewController of UINavigationController by method other than initWithRootViewController
(5 answers)
Closed 4 years ago.
Initially my app starts with a view controller(TabBarView) which I have set in AppDelegate file.
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let tabBarView = TabBarView()
navigationController = UINavigationController(rootViewController: tabBarView)
window?.rootViewController = navigationController
Later in an app, when few criteria are met, I want to change my rootController to a new one(MusicPage).
At the moment I've create a new NavigationController object to display my (MusicPage)viewController however I think that my (TabBarView)viewController might be running in background and consuming memory.
I would really appreciate if someone tells me how to change my initial rootViewController.
Thanks. :)
The answer can be found on
Set rootViewController of UINavigationController by method other than initWithRootViewController
let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var homeViewController = mainStoryboard.instantiateViewControllerWithIdentifier("HomeViewController") as! HomeViewController
let nav = UINavigationController(rootViewController: homeViewController)
appdelegate.window!.rootViewController = nav
Edited: SWIFT 4
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let yourVc = UIViewController() // your view controller
appDelegate.window?.rootViewController = yourVc
appDelegate.window?.makeKeyAndVisible()
Related
its shows two navigationBarControllers!
Top blue and below default NavigationBar.
var rootVC = CustomNavigationController()
let tabbarViewController = UIStoryboard(name: AppStoryboard.dashboard.rawValue, bundle: nil).instantiateViewController(withIdentifier: "TabBarViewController") as! TabBarViewController
rootVC = CustomNavigationController.init(rootViewController: tabbarViewController)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = rootVC
If you already have navigation controller before Tabbar, you dont need to create another navigation controller for each of viewController inside that Tabbar
When a user launches the app from a push notification I present one view controller, then push another. My code to present the first VC is as follows
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeNav: UIViewController = mainStoryBoard.instantiateViewController(withIdentifier: "HomeNavController") as! UINavigationController
let homePageTableVC = mainStoryBoard.instantiateViewController(withIdentifier: String(describing: HomePageTableViewController.self)) as! HomePageTableViewController
homePageTableVC.tipToPresent = tipDay
homeNav.addChildViewController(homePageTableVC)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = homeNav
self.window?.makeKeyAndVisible()
The tipToPresent property is used by the homePageTableVC (in the viewDidLoad method) to then present the second VC, using this code:
if let tipDayToPresent = tipToPresent {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tipVC = storyboard.instantiateViewController(withIdentifier: String(describing: TipViewController.self)) as! TipViewController
tipVC.dayOfTip = tipDayToPresent
tipToPresent = nil
navigationController?.pushViewController(tipVC, animated: true)
}
This works well, but when I press the back button to return to the homePageTableVC, the navigation bar is blank. The title image, menu button, and right bar button that normally show up are not visible.
Any help is appreciated.
Good if solution by #augie works. I would suggest you should not change navigation stack when you handle push notification deep link. It should behave same as it does in normal app launch. By that way you don't need to handle any edge case and no need to set up different window.
Solution: Whenever someone click on push notification dismiss all presented controller and popToRootViewController and then navigate to desired screen.
Can you try changing this
homeNav.addChildViewController(homePageTableVC)
to this
homeNav.setViewControllers([homePageTableVC], animated: false)
I believe the problem is how you are adding your table on the navigation controller. Instead of making it your navigation's root viewcontroller you are adding it as a child vc.
Changing your code like this should work:
let mainStoryBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// Remove type UIViewController
let homeNav = mainStoryBoard.instantiateViewController(withIdentifier: "HomeNavController") as! UINavigationController
let homePageTableVC = mainStoryBoard.instantiateViewController(withIdentifier: String(describing: HomePageTableViewController.self)) as! HomePageTableViewController
homePageTableVC.tipToPresent = tipDay
// Set controllers instead of adding child
homeNav.setViewControllers([homePageTableVC], animated: false)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = homeNav
self.window?.makeKeyAndVisible()
Here is the code
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "homeTBC") as! UITabBarController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
cant figure it yet.
I have tried this code in My App for root view controller in app delegate working perfect:
As I think you are using this code in presented view controller or in presented navigation controller: Please send the scenario(Screen Shot) exact what you are doing?
var window: UIWindow?
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "TabbarVC") as! TabbarVC
self.window?.rootViewController = vc
From Apple's Documentation
When creating windows, always set the window’s initial size and
specify the screen on which it is displayed.
Add the size:
self.window = UIWindow.init(frame: UIScreen.main.bounds)
Your complete code should be like that:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "homeTBC") as! UITabBarController
self.window = UIWindow.init(frame: UIScreen.main.bounds)
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
I have some code to only show the first view controller in my storyboard on the first launch of the app. After that I want to skip that page and go straight to my second view on each launch. I have embedded the first view (which is connected to the second) in a navigation controller.
My issue is that after the first launch when the app goes to the second view directly it's showing the view without the navigation bar on top and I'm not sure why.
In my appdelegate:
func firstLaunchCheck(){
let launchedBefore = UserDefaults.standard.bool(forKey: "launchedBefore")
if launchedBefore{
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialView : UIViewController = storyboard.instantiateViewController(withIdentifier: "mainScreen") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialView
self.window?.makeKeyAndVisible()
}
else{
UserDefaults.standard.set(true, forKey: "launchedBefore")
}
}
UPDATE:
I wound up just changing which view controller were embedded in the navigation controller (excluded the first one) since it didn't make sense to me to have it there. So now after the first launch it loads the navigation controller
SecondViewController is not added in UINavigationController hierarchy, to see the navigationBar on top you can push SecondViewController on firstVC if the launchedBefore is false in appDelegate
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondVC = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
let navigationController = window.rootViewController as! UINavigationController
navigationController?.pushViewController(secondVC, animated: false)
You need to embed the second view controller i.e. "mainScreen" in UINavigationController and then make it the rootViewController of your app window.
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = UINavigationController.init(rootViewController: storyboard.instantiateViewController(withIdentifier: "mainScreen"))
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialView
self.window?.makeKeyAndVisible()
At some point in my app I need to go back to my main (i.e. home) ViewController. So I need to travel backwards into my navigation stack which by now is full with ViewControllers and NavigationControllers. So I do the following:
// to dismiss the current VC
self.navigationController?.popViewControllerAnimated(true)
// to go back home
UIApplication.sharedApplication().keyWindow?.rootViewController = homeNC
homeNC is a global var pointing to a NavigationController containing a storyboard instance of my main "home" ViewController.
It works, but partially. Meaning, it does take me back to my home ViewController but it then becomes unresponsive to touches and scrolling. Nothing responds, neither the navigationBar buttons nor the TableViewCells inside the home NC/VC. Xcode doesn't crash, just sits there waiting.
I can't figure out why. Can anyone think what I'm missing here?
** EDIT **
Maybe it's because I am embedding a nested VC inside my main (home) VC. Here's the code and what else I tried since:
homeNC = self.navigationController!
homeVC = self
let discoverVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("DiscoverVC") as UIViewController
// embed discoverVC in this VC
self.addChildViewController(discoverVC)
self.view.addSubview(discoverVC.view)
discoverVC.didMoveToParentViewController(self)
// store self NC for using it by "thank you" VC to come back to home after payment
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
// navigates back but becomes unresponsive
appDelegate.window?.rootViewController = homeVC
// navigates back but becomes unresponsive
appDelegate.window?.rootViewController = homeNC
I also tried saving a reference to the appdelegate window with the following:
// Initialise sideMenu
window = UIWindow(frame: UIScreen.mainScreen().bounds)
let sideMenu = SSASideMenu(contentViewController: UINavigationController(rootViewController: MainViewController()), leftMenuViewController: LeftMenuViewController())
window!.rootViewController = sideMenu
window!.makeKeyAndVisible()
// get a reference to appdelegate's window so that we can navigate back later
mainWindow = window!
but again it doesn't navigate back when I do:
appDelegate.window?.rootViewController = mainWindow.rootViewController
Try this. I will work for you.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window?.rootViewController = mainVC
EDIT
I read out your edited question. Problem is occurring due to SSASideMenu. I updated my answer and I hope now it will work for you. You have to make two changes. First in AppDelegate.swift, make property of SSASideMenu like this:
var window: UIWindow?
var sideMenu: SSASideMenu!
Now your code will be changed to:
sideMenu = SSASideMenu(contentViewController: UINavigationController(rootViewController: MainViewController()), leftMenuViewController: LeftMenuViewController())
Now if you want to change the view-controller, you have to change the contentViewController of SSASideMenu like this:
func showDiscoverVC() {
//Instantiate ViewController
let discoverVC: UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("DiscoverVC") as UIViewController
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.sideMenu.contentViewController = UINavigationController(rootViewController: discoverVC)
}