Change root View Controller
For 1) you can't present a view controller using a segue and then use it to replace the root view controller in the prepare. You will need to instantiate the tab view controller from the storyboard and then replace the root view controller.
Something like this:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "TabController")
UIApplication.shared.keyWindow?.rootViewController = vc
(assuming the storyboard is called 'Main' and you give the tab controller the storyboard ID of 'TabController'.
I'm not quite clear on what the issue is for 2.
However as a general note I would approach this differently and instead of having the login controller as your initial view controller have the tab bar as the initial controller and then just present the login controller the first time the app starts. That way you avoid replacing the root controller at all and it's all more controlled.
Programmatically change rootViewController of storyBoard
Objective-C:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UITabBarController *rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"tabBarcontroller"];
[[UIApplication sharedApplication].keyWindow setRootViewController:rootViewController];
Swift :
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewControllerWithIdentifier("tabBarcontroller") as UITabBarController
UIApplication.sharedApplication().keyWindow?.rootViewController = viewController;
Swift 3:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = viewController
Swift 5:
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
UIApplication.shared.windows.first?.rootViewController = viewController
UIApplication.shared.windows.first?.makeKeyAndVisible()
Or simply like this:
let viewController = mainStoryboard.instantiateViewController(withIdentifier: "tabBarcontroller") as! UITabBarController
self.view.window?.rootViewController = viewController
self.view.window?.makeKeyAndVisible()
Both works fine!
Change root ViewController programmatically
Set this in appDelegate's didFinishLaunchingWithOptions
method according to current app settings , also you should use window
not keyWindow
if(userExists)
{
let vc = storyboard.instantiateViewController(withIdentifier: "tabBarVC")
UIApplication.shared.window.first?.rootViewController = vc
}
else
{
let vc = storyboard.instantiateViewController(withIdentifier: "loginVC")
UIApplication.shared.window.first?.rootViewController = vc
}
Don't use present as this will automatically change the root
Also another way to access windows (used when AppDelegate has a value)
let appDelegate = UIApplication.shared.delegate as? AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let homeController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
appDelegate?.window?.rootViewController = homeController
How to change rootViewController in swift?
First you need to get the Window from SceneDelegate and use that window for rootViewController.
Suggestion: Whenever we are using rootViewController then no need to do present and push thing it will automatically set as a main home viewcontroller(Intial viewController)
let window = (UIApplication.shared.connectedScenes.first!.delegate as! SceneDelegate).window
let storyboard = UIStoryboard(name: "Main", bundle:nil)
if UserDefaults.standard.bool(forKey: "LoggedIn") == false {
let vc =storyboard.instantiateViewController(withIdentifier: "EnterPin") as! UINavigationController
window?.rootViewController = vc
window?.makeKeyAndVisible()
} else if UserDefaults.standard.bool(forKey: "LoggedIn") == true {
let vc =storyboard.instantiateViewController(withIdentifier: "MainController") as! UINavigationController
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
I suggest you do all this things in SceneDelegate file
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: scene)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if UserDefaults.standard.bool(forKey: "LoggedIn") == false {
let vc = storyboard.instantiateViewController(withIdentifier: "EnterPin") as! UINavigationController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
} else if UserDefaults.standard.bool(forKey: "LoggedIn") == true {
let vc = storyboard.instantiateViewController(withIdentifier: "MainController") as! UINavigationController
self.window?.rootViewController = vc
self.window?.makeKeyAndVisible()
}
}
I Hope it is helpful for you!
IOS | Unable to change root view controller in app delegate
If you are targeting only iOS 13+
, the only change you should need to make is to add one line:
window?.rootViewController = initialViewController
// add this line
self.window = window
window?.makeKeyAndVisible()
If you want to support earlier iOS versions, here is a complete SceneDelegate / AppDelegate implementation:
SceneDelegate.swift
//
// SceneDelegate.swift
// Created by Don Mag on 3/27/20.
//
import UIKit
// entire class is iOS 13+
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
print("Scene Delegate willConnectTo", UserDefaults.standard.bool(forKey: "isLoggedIn"))
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window.windowScene = windowScene
if UserDefaults.standard.bool(forKey: "isLoggedIn") {
guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeVC") as? TabController else {
fatalError("Could not instantiate HomeVC!")
}
window.rootViewController = vc
} else {
guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AuthVC") as? AuthViewController else {
fatalError("Could not instantiate HomeVC!")
}
window.rootViewController = vc
}
self.window = window
window.makeKeyAndVisible()
}
}
AppDelegate.swift
//
// AppDelegate.swift
// Created by Don Mag on 3/27/20.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window : UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
if #available(iOS 13, *) {
// do only pure app launch stuff, not interface stuff
} else {
print("App Delegate didFinishLaunching... isLoggedIn:", UserDefaults.standard.bool(forKey: "isLoggedIn"))
self.window = UIWindow()
if UserDefaults.standard.bool(forKey: "isLoggedIn") {
guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeVC") as? TabController else {
fatalError("Could not instantiate HomeVC!")
}
window?.rootViewController = vc
} else {
guard let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AuthVC") as? AuthViewController else {
fatalError("Could not instantiate HomeVC!")
}
window?.rootViewController = vc
}
window?.makeKeyAndVisible()
}
return true
}
// MARK: UISceneSession Lifecycle
// iOS 13+ only
@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
// iOS 13+ only
@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
}
}
Changing the rootViewController of a UIWindow
It turns out there are two separate issues. 1) I had a retain cycle in Controller A so it was never getting dealloc'd. Secondly, in order to change the root view controller you must remove the windows subviews first (even though the docs suggest otherwise)
Update root view controller after user login + iOS 13 and later
This is how I managed navigation for both the older version and the new version. So when the user has the latest iOS we need to setup root from sceneDelegate
and for older version we need to setup root from appDelegate
AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13, *) {
} else {
setupRoot()
}
return true
}
// MARK: UISceneSession Lifecycle
@available(iOS 13.0, *)
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
@available(iOS 13.0, *)
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
}
func setupRoot() {
//Setup Your Root Here
//window?.rootViewController = objNavigationVC
//window?.makeKeyAndVisible()
}
}
SceneDelegate.swift
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window = window
appDelegate.setupRoot()
}
}
set root view controller in main storyboard
change storyboard--> viewcontroller---> attribute inspector---> change presentation from Automatic to Full Screen
Related Topics
How to Hide a Status Bar in Ios
Resize Uiimage With Aspect Ratio
How to Determine the Os Version At Runtime in Os X or iOS (Without Using Gestalt)
Uinavigationbar Hide Back Button Text
Setting Custom Uitableviewcells Height
iOS 7 Tableview Like in Settings App on iPad
iPhone Sdk: Differencebetween Loadview and Viewdidload
How to Create .Ipa File Using Xcode
Iphone Smooth Sketch Drawing Algorithm
How to Make Uilabel Display Outlined Text
How to Create a Swift Date Object
How Would I Tint an Image Programmatically on Ios
Modal View Controllers - How to Display and Dismiss