Set rootViewController programmatically not working, picking initial view controller from storyboard only in Xcode 11
Got the answer by doing some more google, i mean stackoverflow.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
let storyboard = UIStoryboard(name: "Main", bundle: nil)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let vc = storyboard.instantiateViewController (withIdentifier: "Primary") as! ViewController
window = UIWindow(windowScene: windowScene)
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
SceneDelegate is used for this purpose since iOS 13 not AppDelegate. Here is the link SceneDelegate example
My Programatically set initial view is not loading
If you are in ios 13 or above you need to use UIWindowSceneDelegate
. Use following method for initialise your app in SceneDelegate
file,
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
if isLogin == false
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
else
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "TabBarVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
}
}
AppDelegate File,
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
if #available(iOS 13.0, *) {
} else {
if isLogin == false
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
else
{
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "TabBarVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
}
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
For below ios 13, no need to initialise window like self.window = UIWindow(frame: UIScreen.main.bounds)
. Just use that application automatically creates window property in AppDelegate
.
set initial viewcontroller in appdelegate - swift
Xcode11 and SceneDelegate note:
Starting from Xcode11, because of SceneDelegates, it's likely that you shouldn't do it inside AppDelegate
. Instead do it from SceneDelegate
. For more on that see this other answer
Old answer:
I used this thread to help me convert the objective C to swift, and its working perfectly.
Instantiate and Present a viewController in Swift
Swift 2 code:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("LoginSignupVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
Swift 3 code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "LoginSignupVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
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
Accessing root view controller in AppDelegate start up
We followed the approach of switching the root view controller when required. We launch the app and if user is not logged in we set the root to LoginViewController. After logging in we set the root back to UISplitViewController. The solution is from https://stackoverflow.com/a/25979945/47281
Switching RootViewController programmatically disables touch
The issue (discovered in the comments on the question) was that an activity indicator was calling beginIgnoringInteractionEvents
.
If anyone else has this issue in the future, it's worth searching the project for this string or anything similar which may disable touch events from occurring.
Related Topics
Uipickerviewdelegate Xcode 8 Swift 3
How to Assign Elements of a Dictionary to JSON Object in Vapor 3
Write Data to Firebase in The Background After Retrieving Steps with Healthkit's Background Delivery
How to Get a Popup Dialog Box in Swift Playgrounds
How to Stop Playback of Avplayerviewcontroller as UIviewrepresentable After Dismissal
Read UId from Nfc Mifare Tag iOS 13
Programmatically Select All Cells in Tableview So Next Time They Are Pressed They Call Diddeselect
Swift Compound Arithmetic Operation Error
Nsattributedstring Boundingrect Returns Wrong Height
Extending Dictionary with Key and Value Constraints
How to Load Lcr Image in Tvos Apps
How to Hide The Top Bar (With Buttons) Usin Swift and Macos
Spacing Between Sections in a Form
Image to String Using Base64 in Swift 4