iosswiftrootviewcontrolleruiscenedelegate

Update root view controller after user login + iOS 13 and later


Using scene delegate I'm able to set the root view controller.(I'm using Xcode 11.3 and iOS version 13.3 and running my app on iPhone 6+ with iOS 12.4)

What I want is when user login, I need to update the root view controller. For that I did the following

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
static let shared = SceneDelegate()

  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

      //some code is here
  }
}

@available(iOS 13.0, *)
extension SceneDelegate {

  func setRootViewControllerBasedOnLogin() {

    if let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogin"), isLoggedIn {

        let tabbar = UIStoryboard(name: "Other", bundle: nil).instantiateViewController(withIdentifier: "Tabbar") as! UITabBarController

        if var vcs = tabbar.viewControllers {
            vcs.remove(at: 2)
            tabbar.viewControllers = vcs
        }
        self.window?.rootViewController = tabbar

    } else {
       //other stuff
    }
  }
}

So when user login in to the app I need to remove a tab item from tab bar and update the root view controller.

So I'm doing as follows.

func processLogin() {

  //performing login in this method so when login successful we setting root view controller
  callLoginAPI { response in

    if response.isSuccess {
       UserDefaults.standard.set(true, forKey: "isLogin")
       if #available(iOS 13.0, *) {
           SceneDelegate.shared.setRootViewControllerBasedOnLogin()
        } else {
          // Fallback on earlier versions
        }
    }
  }
}

When I'm doing this nothing happened. I'm not able to change the root view controller of the app after user successfully login into the app?

Any suggestions? what am I doing wrong?


Solution

  • 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<UISceneSession>) {
    
        }
    
        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()
        }
    }