Related
I'm implementing Firebase Google Sign in for a toy app. After Google sign in, the app suppose to move from SignInViewController to HomePageViewController. According the firebase instructions (https://firebase.google.com/docs/auth/ios/google-signin),
1. GDSignInButton is installed in SignInViewController
2. AppDelegate should implement sign() of GDSignInDelegate.
Before the end of sign(), which is in AppDelegate, how should I tell SignInViewController that, you can move to HomePageViewController. I have successfully followed the instructions and finished sign in. But I don't know how to transition the view controllers in AppDelegate.
Note that, in Xcode 11.5, there is a SceneDelegate, which owns a window that used to belong to AppDelegate in older version. So we can't get the reference to a Window, which contains view controllers, in AppDelegate. Thanks in advance!
My problem is solved. Thanks to those who helped! But my question remains: Imagine you are in AppDelegate, how do you communicate with (access) your views?
Here is my code to do it in iOS 13:
AppDelegate.swift
import Firebase
import GoogleSignIn
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// configure de firebase app
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
// other methods in app delegate
#available(iOS 9.0, *)
func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
}
SceneDelegate.swift
import Firebase
import GoogleSignIn
import FirebaseAuth
// conform to the google sign in delegate
class SceneDelegate: UIResponder, UIWindowSceneDelegate, GIDSignInDelegate {
var window: UIWindow?
// when the app launches, it checks if the user is signed in, and redirect to the correct view controller
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
if Auth.auth().currentUser != nil {
// redirect to the home controller
self.window!.rootViewController = storyboard.instantiateViewController(withIdentifier: "HomeTabBarController")
self.window!.makeKeyAndVisible()
} else {
// redirect to the login controller
self.window!.rootViewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
self.window!.makeKeyAndVisible()
}
}
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
}
// handle the sign in to redirect to the home controller
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error?) {
if error != nil {
return
}
guard let authentication = user.authentication else { return }
let credential = GoogleAuthProvider.credential(withIDToken: authentication.idToken, accessToken: authentication.accessToken)
Auth.auth().signIn(with: credential) { (authResult, error) in
if let error = error {
print(error.localizedDescription)
return
}
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// redirect the user to the home controller
self.window!.rootViewController = storyboard.instantiateViewController(withIdentifier: "HomeTabBarController")
self.window!.makeKeyAndVisible()
}
}
func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
// Perform any operations when the user disconnects from app here.
// ...
}
}
If your project uses SceneDelegate then you must use the following code to get to the key window. From keyWindow you can get to rootViewController by using .rootViewController and down-cast it as MyViewController and access it accordingly.
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
let myViewContorller = keyWindow?.rootViewController as? MyViewController
In appDelegate:-
It is possible by passing it as RootViewController
func application(application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController : UIViewController = storyBoard.instantiateViewControllerWithIdentifier(“InitialControllerID”) as InitialViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}
Or if rootViewController is of type UINavigation Controller then push your home screen over it like:-
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let rootViewController = self.window!.rootViewController as! UINavigationController
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = mainStoryboard.instantiateViewController(withIdentifier: “InitialControllerID") as! InitialViewController
rootViewController.pushViewController(viewController, animated: true)
return true
}
Or
On the basis of this article:- “https://www.dev2qa.com/how-to-set-application-root-view-controller-programmatically-in-xcode-11/“
For iOS 13
In SceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options `connectionOptions: UIScene.ConnectionOptions) {`
// If this scene's self.window is nil then set a new UIWindow object to it.
self.window = self.window ?? UIWindow()
// Set this scene's window's background color.
self.window!.backgroundColor = UIColor.red
// Create a ViewController object and set it as the scene's window's root view controller.
self.window!.rootViewController = ViewController()
// Make this scene's window be visible.
self.window!.makeKeyAndVisible()
guard scene is UIWindowScene else { return }
}
After upgrading Xcode a critical part of my application has stopped working.
When my app launches I run a function to check boolean flags and set the correct rootViewController.
But the code I have been using to set this has now stopped working
class func setLoginAsInitialViewContoller(window:UIWindow) {
print("SET LOGIN")
let storyboard = UIStoryboard(name: "Login", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
controller.modalPresentationStyle = .overFullScreen
window.rootViewController = controller
window.makeKeyAndVisible()
}
Specifically when the app gets the the second last line window.rootViewController = controller it crashes with a libc++abi.dylib: terminating with uncaught exception of type NSException error.
The above function is in a class called Utilities.swift and I am calling the function from within my AppDelegate.swift as shown below:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var storyboard: UIStoryboard? = nil
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.isIdleTimerDisabled = true
Utilities.decideInitialViewController(window: self.window!)
return true
}
Any solutions or fixes on how I can set the root controller is much appreciated.
Thank!
This is because AppDelegate doesn't have window property anymore.
Now you must use SceneDelegate's scene(_:willConnectTo:options:) method to change root view controller.
Like shown in this example:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
// Instantiate UIWindow with scene
let window = UIWindow(windowScene: scene)
// Assign window to SceneDelegate window property
self.window = window
// Set initial view controller from Main storyboard as root view controller of UIWindow
self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
// Present window to screen
self.window?.makeKeyAndVisible()
}
It is available in SceneDelegate.swift file in your project
It will have delegate method :
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
Example
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
self.window = UIWindow(windowScene: windowScene)
let initialViewController =
storyboard.instantiateViewController(withIdentifier: "FirstViewController")
self.window!.rootViewController = initialViewController
self.window!.makeKeyAndVisible()
}
}
In viewDidAppear you can set root:-
override func viewDidAppear(_ animated: Bool) {
print(self.view.window)
let vc = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
self.view.window?.rootViewController = vc
}
For anyone looking to create a couple of extensions to change the root view controller and need to support both delegate types (UISceneDelegate and AppDelegate), here's a couple:
extension UIViewController {
var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var sceneDelegate: SceneDelegate? {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let delegate = windowScene.delegate as? SceneDelegate else { return nil }
return delegate
}
}
And if you're in need of an extension to reach the UIWindow from a ViewController with iOS12 and iOS13 Support:
extension UIViewController {
var window: UIWindow? {
if #available(iOS 13, *) {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let delegate = windowScene.delegate as? SceneDelegate, let window = delegate.window else { return nil }
return window
}
guard let delegate = UIApplication.shared.delegate as? AppDelegate, let window = delegate.window else { return nil }
return window
}
}
If you want to use ScenceDelegate. In scene(_:willConnectTo:options:, creates a new UIWindow, sets the window’s rootViewController and makes this window the key window.
If you don't want to use ScenceDelegate, you can try to remove it by following this.
I have following code in my AppDelegate.swift to setup root view controller for an iOS application. But it does not work. It follows Target structure (defined under General tab) and ignores this code.
(Xcode 11, Swift 5.1, iOS 13)
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
guard let rootVC = UIViewController() else {
print("Root VC not found")
return true
}
let rootNC = UINavigationController(rootViewController: rootVC)
window?.rootViewController = rootNC
window?.makeKeyAndVisible()
return true
}
}
Unable to understand where is the issue.
I tried following references also but no luck:
Swift ios set a new root view controller
Root View Controller Swift
iOS: Root Controller Navigation
To choose a previous approach to the one supported by SwiftUI, from a project created in Xcode 11, you can follow these steps.
I tried following two options and both of these working for me. With iOS-13 (Xcode 11) a new file SceneDelegate.swift with the concept of UIWindowScene is enabled by default.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
//self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
guard let rootVC = storyboard?.instantiateViewController(identifier: "ViewControllerIdentifierName") as? ViewController else {
print("ViewController not found")
return
}
let rootNC = UINavigationController(rootViewController: rootVC)
self.window?.rootViewController = rootNC
self.window?.makeKeyAndVisible()
}
}
Alternate:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let windowScene = UIWindowScene(session: session, connectionOptions: connectionOptions)
self.window = UIWindow(windowScene: windowScene)
//self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
guard let rootVC = storyboard?.instantiateViewController(identifier: "ViewControllerIdentifierName") as? ViewController else {
print("ViewController not found")
return
}
let rootNC = UINavigationController(rootViewController: rootVC)
self.window?.rootViewController = rootNC
self.window?.makeKeyAndVisible()
}
}
I don't know, why and how it works but it resolved my problem.
Reference docs that helped me:
init(windowScene:)
UIWindow
rootViewController
I tried the following approach and it's working for me in iOS 13 and also tested on iOS 12.4.2 from Xcode 11.
func resetRoot() {
guard let rootVC = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ViewController") as? ViewController else {
return
}
let navigationController = UINavigationController(rootViewController: rootVC)
UIApplication.shared.windows.first?.rootViewController = navigationController
UIApplication.shared.windows.first?.makeKeyAndVisible()
}
First Case
If major of your project is build in storyboard and before Xcode 11 is used for development and you are not using SwiftUI you want to use your old classes associated with AppDelegate.
Then try to remove "Application Scene Manifest" in info.pllist.
Remove ScenceDelegate from project completely.
Then you will able to use your old code.
Second Case
If you want to use both Appdelegte and ScenceDelegate then below is working code.
App Delegate Code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *){
//do nothing we will have a code in SceneceDelegate for this
} else {
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let VC = mainStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
navigationController?.isNavigationBarHidden = true
navigationController = UINavigationController(rootViewController: VC)
navigationController?.isNavigationBarHidden = true // or not, your choice.
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window!.rootViewController = navigationController
}
return true
}
ScenceDelegate Code:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let VC = mainStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
navigationController?.isNavigationBarHidden = true
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window.windowScene = windowScene
window.rootViewController = VC
window.makeKeyAndVisible()
let appDelegate = UIapplication.shared.delegate as! AppDelegate
appDelegate.window = window
}
Here's what work for both iOS 13.x and iOS 12.x and below
For iOS 13,In the Scene Delegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
//Make sure to do this else you won't get
//the windowScene object using UIApplication.shared.connectedScenes
self.window?.windowScene = windowScene
let storyBoard: UIStoryboard = UIStoryboard(name: storyBoardName, bundle: nil)
window?.rootViewController = storyBoard.instantiateInitialViewController()
window?.makeKeyAndVisible()
}
In a utility class, I wrote below function to get the window object and assign it to the appdelegate.window. According to my needs, I needed to set root view controller at multiple places in different scenarios for which I needed the window object.
static func redirectToMainNavRVC(currentVC: UIViewController){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let vc = UIStoryboard(name: appDelegate.storyBoardName, bundle: nil).instantiateViewController(withIdentifier: "MainNavigationViewController") as! MainNavigationViewController
if #available(iOS 13.0, *){
if let scene = UIApplication.shared.connectedScenes.first{
guard let windowScene = (scene as? UIWindowScene) else { return }
print(">>> windowScene: \(windowScene)")
let window: UIWindow = UIWindow(frame: windowScene.coordinateSpace.bounds)
window.windowScene = windowScene //Make sure to do this
window.rootViewController = vc
window.makeKeyAndVisible()
appDelegate.window = window
}
} else {
appDelegate.window?.rootViewController = vc
appDelegate.window?.makeKeyAndVisible()
}
}
This worked well for me. Hopefully, it works for others too.
If you don't want to use main storyboard, if you want to create you own views programmatically.
For xcode 11.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: ViewController())
}
This will defenetily work. Thanks
If you follow this answer https://stackoverflow.com/a/58084612/6667477
and if you initialise a rootController programmatically you also have to remove reference to main storyboard from:
Info.plist.
Deployment info
For Xcode 11+ and Swift 5+ inside SceneDelegate.swift
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
let submodules = (
home: HomeRouter.createModule(),
search: SearchRouter.createModule(),
exoplanets: ExoplanetsRouter.createModule()
)
let tabBarController = TabBarModuleBuilder.build(usingSubmodules: submodules)
window.rootViewController = tabBarController
self.window = window
window.makeKeyAndVisible()
}
var window: UIWindow?
has been moved from AppdDelegate.swift to SceneDelegate.swift.
So I used rootViewController in the Scene Delegate class and it works -
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 let tabBarController = window?.rootViewController as? UITabBarController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(identifier: "NavController")
vc.tabBarItem = UITabBarItem(tabBarSystemItem: .topRated, tag: 1)
tabBarController.viewControllers?.append(vc)
}
}
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
self.window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout()
let swipingController = SwipingController(collectionViewLayout: layout)
self.window?.rootViewController = swipingController
}
Important Points to Note:
If you plan to add SwiftUI to existing project, then the project's deployment target must be set to iOS 13, and then the project must have SceneDelegate. You cannot launch the app with just AppDelegate.
(If you are not intending to use SwiftUI, but still need min deployment target to be iOS 13, follow Carlos García's answer above)
If you are trying to add code in SwiftUI, in an already created project , make sure
Minimum deployment Target is set to iOS 13
You have both Appdelegate + SceneDelegate setup correctly
Mainly, have the Application Scene Manifest entry in Info.plist, possibly create a dummy Project and copy entry from there
I just deleted a row on the info.plist that says something about Application scene. Works for me.
let MainViewController = mainStoryboard.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
let nvc:rootNavigation = mainStoryboard.instantiateViewController(withIdentifier: "rootNavigation") as! rootNavigation
nvc.viewControllers = [Mainmap]
leftViewController.mainViewController = nvc
UIApplication.shared.windows.first?.backgroundColor = UIColor(red: 236.0, green: 238.0, blue: 241.0, alpha: 1.0)
UIApplication.shared.windows.first?.rootViewController = nvc
UIApplication.shared.windows.first?.makeKeyAndVisible()
let controller = ....
let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
keyWindow?.rootViewController = controller
keyWindow?.makeKeyAndVisible()
These are the basic code required to set root view controller.
This will help you to set your root view controller through scene delegate.
let navVc = UINavigationController(rootViewController: UIViewController)
navVc.setNavigationBarHidden(true, animated: false )
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let sceneDelegate = windowScene.delegate as? SceneDelegate else { return }
sceneDelegate.window?.rootViewController = navVc
sceneDelegate.window?.makeKeyAndVisible()
I did two things. Firstly I set a Notification into SceneDelegate, then when I needed to change the RootViewController I did a Notification Post and it worked. But it's an anwful solution.
After that
My boss recommended me to change the Controllers of the NavigationController, something like this:
func logged() {
let mainStoryboard: UIStoryboard = UIStoryboard(name: "MainTabViewController", bundle: nil)
let mainVC = mainStoryboard.instantiateInitialViewController()
self.navigationController?.setViewControllers([mainVC!], animated: false)
}
I know that perhaps it's not the best solution, but I see it cleaner.
I'm working now on iOS 13 and I didn't want to use deprecated things.
I am implementing an iOS app. when User Launch the application first time, I need to navigate to another page and from next time onwards I need to navigate Home Page. How to do this task in iOS swift?
Updated: if you get this error: "Value of type 'AppDelegate' has no member 'window' ".
Answer is : you have to write your codes inside of SceneDelegate.swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let defaults = UserDefaults.standard
guard let a=UserDefaults.standard.object(forKey: "wantOverview") else {
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "firstTimeViewController") as! firstTimeViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
defaults.set(false, forKey: "wantOverview")
return
}
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
guard let _ = (scene as? UIWindowScene) else { return }
}
The following solution to this common problem assumes that
At the outset — in this example, that's before the "username" key has been set in the user defaults — we want to launch to the storyboard's Initial View Controller (where the user is supposed to set the "username" key).
Thereafter, we always want to launch to a different view controller in the storyboard, whose identifier in this example is "root".
It's very short and simple!
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if let rvc = self.window?.rootViewController {
if UserDefaults.standard.object(forKey:"username") as? String != nil {
self.window!.rootViewController = rvc.storyboard!.instantiateViewControllerWithIdentifier("root")
}
}
return true
}
}
This can be achieved using userdefaults. Just make a new controller like SplashViewController which will only redirect to desired ViewController.
import UIKit
class SplashViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
decideWhichScreenToShow()
}
// This logic will do
func decideWhichScreenToShow(){
if !UserDefaults.standard.bool(forKey: "your_key"){
// This will execute first time, in that controller's viewDidLoad() make this true
}else{
}
}
}
You can write same logic in Appdelegate.
Create func for checking that if your key in UserDefaults or not using this link & Then check by if...else
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
if isKeyPresentInUserDefaults(key: "isFirstTime") {
let home = HomeVC()
window?.rootViewController = home
} else {
let login = LoginVC()
window?.rootViewController = login
UserDefaults.standard.set(true, forKey: "isFirstTime")
}
return true
}
func isKeyPresentInUserDefaults(key: String) -> Bool {
return UserDefaults.standard.object(forKey: key) != nil
}
Try this:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
if firstTime = UserDefaults.standard.object(forKey: "firstTime")
{
let storyboard = UIStoryboard(name: "SecondStoryBoard", bundle: nil)
let MainView = storyboard.instantiateViewController(withIdentifier: "SecondTimeViewController") as! SecondTimeViewController
let navController = UINavigationController.init(rootViewController: MainView)
self.window?.rootViewController = navController
}
else
{
UserDefaults.standard.set(true, forKey: "firstTime")
let storyboard = UIStoryboard(name: "FirstStoryBoard", bundle: nil)
let MainView = storyboard.instantiateViewController(withIdentifier: "FirstTimeViewController") as! FirstTimeViewController
let navController = UINavigationController.init(rootViewController: MainView)
self.window?.rootViewController = navController
}
}
You may use change the didFinishLaunchingWithOptions method in AppDelegate to achieve this.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
guard let firstTime = UserDefaults.standard.object(forKey: "IsFirstTime") else {
UserDefaults.standard.set(true, forKey: "IsFirstTime")
let storyBoard = UIStoryboard.init(name: "FirstStoryBoard", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "FirstControllerId") as! FirstTimeViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
return true
}
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let initialVc = storyBoard.instantiateViewController(withIdentifier: "NormalInitialController") as! ViewController
self.window?.rootViewController = initialVc
self.window?.makeKeyAndVisible()
return true
}
You check if the value for key, "IsFirstTime", exists in UserDefaults. There won't be a value if the app is launching for the first time.
In this case, you can launch your FirstTimeViewController and set a value to the key in UserDefaults.
If a value exists in UserDefaults, just initiate your normal ViewController.
I would like to set the initial viewcontroller from the appdelegate. I found a really good answer, however it's in Objective C and im having trouble achieving the same thing in swift.
Programmatically set the initial view controller using Storyboards
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *viewController = // determine the initial view controller here and instantiate it with [storyboard instantiateViewControllerWithIdentifier:<storyboard id>];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
Anyone able to help?
I want the initial Viewcontroller to be dependent on certain conditions being met using a conditional statement.
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
}
For new Xcode 11.xxx and Swift 5.xx, where the target it set to iOS 13+.
For the new project structure, AppDelegate does not have to do anything regarding rootViewController.
A new class is there to handle window(UIWindowScene) class -> 'SceneDelegate' file.
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = // Your RootViewController in here
self.window = window
window.makeKeyAndVisible()
}
}
Try this. For example:
You should use UINavigationController as the initial view controller. Then, you can set any view controller as root from the storyboard.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyboard.instantiateInitialViewController() as UINavigationController
let rootViewController = storyboard.instantiateViewControllerWithIdentifier("VC") as UIViewController
navigationController.viewControllers = [rootViewController]
self.window?.rootViewController = navigationController
return true
}
See my storyboard screen.
Swift 3, Swift 4:
Change first line to
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
the rest is same.
Swift 5+:
Instantiate root view controller from storyboard:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// this line is important
self.window = UIWindow(frame: UIScreen.main.bounds)
// In project directory storyboard looks like Main.storyboard,
// you should use only part before ".storyboard" as its name,
// so in this example name is "Main".
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
// controller identifier sets up in storyboard utilities
// panel (on the right), it is called 'Storyboard ID'
let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}
If you want to use UINavigationController as root:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// this line is important
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController
let navigationController = UINavigationController.init(rootViewController: viewController)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
Instantiate root view controller from xib:
It is almost the same, but instead of lines
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "YourViewControllerIdentifier") as! YourViewController
you'll have to write
let viewController = YourViewController(nibName: "YourViewController", bundle: nil)
if you are not using storyboard, you can try this
var window: UIWindow?
var initialViewController :UIViewController?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
initialViewController = MainViewController(nibName:"MainViewController",bundle:nil)
let frame = UIScreen.mainScreen().bounds
window = UIWindow(frame: frame)
window!.rootViewController = initialViewController
window!.makeKeyAndVisible()
return true
}
Code for Swift 4.2 and 5 code:
var window: UIWindow?
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: "dashboardVC")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
And for Xcode 11+ and for Swift 5+ :
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = // Your RootViewController in here
self.window = window
window.makeKeyAndVisible()
}
}
}
Here is a good way to approach it. This example places a navigation controller as the root view controller, and puts the view controller of your choice within it at the bottom of the navigation stack, ready for you to push whatever you need to from it.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
// mainStoryboard
let mainStoryboard = UIStoryboard(name: "MainStoryboard", bundle: nil)
// rootViewController
let rootViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MainViewController") as? UIViewController
// navigationController
let navigationController = UINavigationController(rootViewController: rootViewController!)
navigationController.navigationBarHidden = true // or not, your choice.
// self.window
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
}
To make this example work you would set "MainViewController" as the Storyboard ID on your main view controller, and the storyboard's file name in this case would be "MainStoryboard.storyboard". I rename my storyboards this way because Main.storyboard to me is not a proper name, particularly if you ever go to subclass it.
I had done it in Objective-C. I hope it will be useful for you.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *viewController;
NSUserDefaults *loginUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *check=[loginUserDefaults objectForKey:#"Checklog"];
if ([check isEqualToString:#"login"]) {
viewController = [storyboard instantiateViewControllerWithIdentifier:#"SWRevealViewController"];
} else {
viewController = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
}
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
Init ViewController in AppDelegate
[Initial View Controller]
Disable Main.storyboard
General -> Deployment Info -> Main Interface -> remove `Main`
Info.plist -> remove Key/Value for `UISceneStoryboardFile` and `UIMainStoryboardFile`
Add Storyboard ID
Main.storyboard -> Select View Controller -> Inspectors -> Identity inspector -> Storyboard ID -> e.g. customVCStoryboardId
[previos]
Swift 5 and Xcode 11
Extend UIWindow
class CustomWindow : UIWindow {
//...
}
Edit generated by Xcode SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: CustomWindow!
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewController = storyboard.instantiateViewController(withIdentifier: "customVCStoryboardId")
//or if your storyboard has `Is Initial View Controller`
let storyboard = UIStoryboard(name: String(describing: SomeViewController.self), bundle: nil)
let initialViewController = storyboard.instantiateInitialViewController()
window = CustomWindow(windowScene: windowScene)
window.rootViewController = initialViewController
window.makeKeyAndVisible()
}
//...
}
[Access to Framework bundle]
[Get storyboard from a framework]
If you're not using the storyboard. You can initialize your main view controller programmatically.
Swift 4
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let rootViewController = MainViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}
And also remove Main from Deployment Info.
I had done in Xcode 8 and swift 3.0 hope it will be useful for u, and its working perfectly. Use following code :
var window: UIWindow?
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: "ViewController")
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
return true
}
And If you are using the navigation controller, then use following code for that:
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController:UINavigationController = storyboard.instantiateInitialViewController() as! UINavigationController
let initialViewController = storyboard.instantiateViewControllerWithIdentifier("ViewController")
navigationController.viewControllers = [initialViewController]
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
return true
}
Swift 4:
Add these lines inside AppDelegate.swift, within the didFinishLaunchingWithOptions() function...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Setting the Appropriate initialViewController
// Set the window to the dimensions of the device
self.window = UIWindow(frame: UIScreen.main.bounds)
// Grab a reference to whichever storyboard you have the ViewController within
let storyboard = UIStoryboard(name: "Name of Storyboard", bundle: nil)
// Grab a reference to the ViewController you want to show 1st.
let initialViewController = storyboard.instantiateViewController(withIdentifier: "Name of ViewController")
// Set that ViewController as the rootViewController
self.window?.rootViewController = initialViewController
// Sets our window up in front
self.window?.makeKeyAndVisible()
return true
}
Now, for example, many times we do something like this when we want to either drive the user to a login screen or to a initial setup screenl or back to the mainScreen of the app, etc. If you want to do something like that too, you can use this point as a fork-in-the-road for that.
Think about it. You could have a value stored in NSUserDefaults for instance that held a userLoggedIn Boolean and if userLoggedIn == false { use this storyboard & initialViewController... } else { use this storyboard & initialViewController... }
Well all the answers above/below are producing a warning about no entry point in storyboard.
If you want to have 2 (or more) entry view controllers that depend on some condition (say conditionVariable) then what you should do is:
In your Main.storyboard create UINavigationController without rootViewController, set it as entry point
Create 2 (or more) "Show" segues into view controllers, assign them some id, say id1 and id2
Use next code:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let navigationController = window!.rootViewController! as! UINavigationController
navigationController.performSegueWithIdentifier(conditionVariable ? "id1" : "id2")
return true
}
Hope this helps.
Here is complete Solution in Swift 4
implement this in didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let isLogin = UserDefaults.standard.bool(forKey: "Islogin")
if isLogin{
self.NextViewController(storybordid: "OtherViewController")
}else{
self.NextViewController(storybordid: "LoginViewController")
}
}
write this Function any where inside Appdelegate.swift
func NextViewController(storybordid:String)
{
let storyBoard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let exampleVC = storyBoard.instantiateViewController(withIdentifier:storybordid )
// self.present(exampleVC, animated: true)
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = exampleVC
self.window?.makeKeyAndVisible()
}
Just in case you want to do it in the view controller and not in the app delegate: Just fetch the reference to the AppDelegate in your view controller and reset it's window object with the right view controller as it's rootviewController.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let yourVC = mainStoryboard.instantiateViewControllerWithIdentifier("YOUR_VC_IDENTIFIER") as! YourViewController
appDelegate.window?.rootViewController = yourVC
appDelegate.window?.makeKeyAndVisible()
For swift 4.0.
In your AppDelegate.swift file in didfinishedlaunchingWithOptions method, put the following code.
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
let rootVC = MainViewController() // your custom viewController. You can instantiate using nib too. UIViewController(nib name, bundle)
//let rootVC = UIViewController(nibName: "MainViewController", bundle: nil) //or MainViewController()
let navController = UINavigationController(rootViewController: rootVC) // Integrate navigation controller programmatically if you want
window?.rootViewController = navController
return true
}
Hope it will work just fine.
Swift 5 & Xcode 11
So in xCode 11 the window solution is no longer valid inside of appDelegate. They moved this to the SceneDelgate. You can find this in the SceneDelgate.swift file.
You will notice it now has a var window: UIWindow? present.
In my situation I was using a TabBarController from a storyboard and wanted to set it as the rootViewController.
This is my code:
sceneDelegate.swift
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).
self.window = self.window ?? UIWindow()//#JA- If this scene's self.window is nil then set a new UIWindow object to it.
//#Grab the storyboard and ensure that the tab bar controller is reinstantiated with the details below.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
for child in tabBarController.viewControllers ?? [] {
if let top = child as? StateControllerProtocol {
print("State Controller Passed To:")
print(child.title!)
top.setState(state: stateController)
}
}
self.window!.rootViewController = tabBarController //Set the rootViewController to our modified version with the StateController instances
self.window!.makeKeyAndVisible()
print("Finished scene setting code")
guard let _ = (scene as? UIWindowScene) else { return }
}
Make sure to add this to the correct scene method as I did here. Note that you will need to set the identifier name for the tabBarController or viewController you are using in the storyboard.
In my case I was doing this to set a stateController to keep track of shared variables amongst the tab views. If you wish to do this same thing add the following code...
StateController.swift
import Foundation
struct tdfvars{
var rbe:Double = 1.4
var t1half:Double = 1.5
var alphaBetaLate:Double = 3.0
var alphaBetaAcute:Double = 10.0
var totalDose:Double = 6000.00
var dosePerFraction:Double = 200.0
var numOfFractions:Double = 30
var totalTime:Double = 168
var ldrDose:Double = 8500.0
}
//#JA - Protocol that view controllers should have that defines that it should have a function to setState
protocol StateControllerProtocol {
func setState(state: StateController)
}
class StateController {
var tdfvariables:tdfvars = tdfvars()
}
Note: Just use your own variables or whatever you are trying to keep track of instead, I just listed mine as an example in tdfvariables struct.
In each view of the TabController add the following member variable.
class SettingsViewController: UIViewController {
var stateController: StateController?
.... }
Then in those same files add the following:
extension SettingsViewController: StateControllerProtocol {
func setState(state: StateController) {
self.stateController = state
}
}
What this does is allows you to avoid the singleton approach to passing variables between the views. This allows easily for the dependency injection model which is much better long run then the singleton approach.
Swift 5.3 + and iOS 13.0 +
Set your initial ViewController in "SceneDelegate.swift" // Only
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
setInitialViewController()
window?.makeKeyAndVisible()
}
func setInitialViewController() {
// Set Story board Controller
/*
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController")
*/
// Set Custom Xib
let vc = FrontVC(nibName: "FrontViewController", bundle: nil)
// Navigation Controller
let nav = UINavigationController(rootViewController: vc)
nav.isNavigationBarHidden = true
window?.rootViewController = nav
}
iOS 13+
In the SceneDelegate:
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options
connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
let vc = UIViewController() //Instead of UIViewController() we initilise our initial viewController
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
I worked out a solution on Xcode 6.4 in swift.
// I saved the credentials on a click event to phone memory
#IBAction func gotobidderpage(sender: AnyObject) {
if (usernamestring == "bidder" && passwordstring == "day303")
{
rolltype = "1"
NSUserDefaults.standardUserDefaults().setObject(usernamestring, forKey: "username")
NSUserDefaults.standardUserDefaults().setObject(passwordstring, forKey: "password")
NSUserDefaults.standardUserDefaults().setObject(rolltype, forKey: "roll")
self.performSegueWithIdentifier("seguetobidderpage", sender: self)
}
// Retained saved credentials in app delegate.swift and performed navigation after condition check
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let usernamestring = NSUserDefaults.standardUserDefaults().stringForKey("username")
let passwordstring = NSUserDefaults.standardUserDefaults().stringForKey("password")
let rolltypestring = NSUserDefaults.standardUserDefaults().stringForKey("roll")
if (usernamestring == "bidder" && passwordstring == "day303" && rolltypestring == "1")
{
// Access the storyboard and fetch an instance of the view controller
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var viewController: BidderPage = storyboard.instantiateViewControllerWithIdentifier("bidderpageID") as! BidderPage
// Then push that view controller onto the navigation stack
var rootViewController = self.window!.rootViewController as! UINavigationController
rootViewController.pushViewController(viewController, animated: true)
}
// Override point for customization after application launch.
return true
}
Hope it helps !
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var exampleViewController: ExampleViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ExampleController") as! ExampleViewController
self.window?.rootViewController = exampleViewController
self.window?.makeKeyAndVisible()
return true
}
Open a viewcontroller with SWRevealViewController From App delegate.
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
let swrevealviewcontroller:SWRevealViewController = storyboard.instantiateInitialViewController() as! SWRevealViewController
self.window?.rootViewController = swrevealviewcontroller
self.window?.makeKeyAndVisible()
For Swift 5+
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let submodules = (
home: HomeRouter.createModule(),
search: SearchRouter.createModule(),
exoplanets: ExoplanetsRouter.createModule()
)
let tabBarController = TabBarModuleBuilder.build(usingSubmodules: submodules)
window.rootViewController = tabBarController
self.window = window
window.makeKeyAndVisible()
}
}
I find this answer helpful and works perfectly for my case when i needed to change the rootviewcontroller if my app user already exist in the keychain or userdefault.
https://stackoverflow.com/a/58413582/6596443