2

I have used SceneDelegate to change the rootviewcontroller after login action. It works fine but when I logout I am not able to perform navigation again.

Here is my code for Scenekit:

 let status = UserDefaults.standard.bool(forKey: UserDefaultKeys.status)
          var rootVC : UIViewController?

          if(status == true){
            rootVC = UIStoryboard(name: AppStoryBoardName.main, bundle: nil).instantiateViewController(withIdentifier: TabBarViewController.className) as? TabBarViewController
          }else{
            rootVC = UIStoryboard(name: AppStoryBoardName.main, bundle: nil).instantiateViewController(withIdentifier: LoginViewController.className) as? LoginViewController
          }

          guard let root = rootVC else {return }
          let nav = UINavigationController(rootViewController: root)
          window?.rootViewController = nav

My logout code:

appUserDefaults.set(false, forKey: UserDefaultKeys.status)
                                             appUserDefaults.synchronize()
            let loginVC = self.storyboard?.instantiateViewController(withIdentifier: LoginViewController.className) as? LoginViewController
            let window = UIApplication.shared.windows.first
            window?.rootViewController = loginVC

And my login Button Action: (It doesnt works after logout action)

guard let controller = self.storyboard?.instantiateViewController(withIdentifier: VerificationViewController.className) as? VerificationViewController else { return }
    controller.mobile = phoneTextField.text ?? ""
    self.navigationController?.pushViewController(controller, animated: true)
ios
  • 955
  • 1
  • 12
  • 35
  • see this for help : [iOS 13: Swift - 'Set application root view controller programmatically' does not work](https://stackoverflow.com/questions/58084127/ios-13-swift-set-application-root-view-controller-programmatically-does-not) – Anbu.Karthik Mar 02 '20 at 06:25
  • @Anbu.Karthik - It does the same which I have used but navigation stops working after logout – ios Mar 02 '20 at 06:35
  • 2
    try this `window?.rootViewController = UINavigationController(rootViewController: loginVC)` – Anbu.Karthik Mar 02 '20 at 06:43
  • It works. What is the catch here? Is this the right way to do this? – ios Mar 02 '20 at 06:49
  • 1
    yes, actually you missed the navigation controller, due to the reason for you created the new root controller – Anbu.Karthik Mar 02 '20 at 06:51

1 Answers1

2

It is not working because there is an inconsistency in hierarchy of view-controllers on logout button action and in sceneKit. In sceneKit code you are embedding your LoginViewController in navigation controller and then assign the navigation controller as the windows root view-controller.

let status = UserDefaults.standard.bool(forKey: UserDefaultKeys.status)
var rootVC : UIViewController?

if(status == true){
    rootVC = UIStoryboard(name: AppStoryBoardName.main, bundle: nil).instantiateViewController(withIdentifier: TabBarViewController.className) as? TabBarViewController
} else{
    rootVC = UIStoryboard(name: AppStoryBoardName.main, bundle: nil).instantiateViewController(withIdentifier: LoginViewController.className) as? LoginViewController
}

guard let root = rootVC else {return }

// Embedding the specific controller in navigation controller and assigning navigation controller as windows root.

let nav = UINavigationController(rootViewController: root)
window?.rootViewController = nav

In that case you will have navigation controller in LoginViewController and the login button action works perfect i.e.

self.navigationController?.pushViewController(controller, animated: true)

But on logout you simply assign your LoginViewController as the windows root i.e.

appUserDefaults.set(false, forKey: UserDefaultKeys.status) appUserDefaults.synchronize()
let loginVC = self.storyboard?.instantiateViewController(withIdentifier: LoginViewController.className) as? LoginViewController
let window = UIApplication.shared.windows.first

// loginVC is not embedded in Navigation Controller

window?.rootViewController = loginVC

After the above transition the LoginViewController will not navigation controller so the optional chaining of pushingViewController in login button action will fails i.e.

self.navigationController?.pushViewController(controller, animated: true)

Keep it consistent by embedding the LoginViewController in Navigation Controller even on logout, update your logout action code to :

appUserDefaults.set(false, forKey: UserDefaultKeys.status) appUserDefaults.synchronize()
let loginVC = self.storyboard?.instantiateViewController(withIdentifier: LoginViewController.className) as? LoginViewController
let window = UIApplication.shared.windows.first

// Embed loginVC in Navigation Controller and assign the Navigation Controller as windows root
let nav = UINavigationController(rootViewController: loginVC)
window?.rootViewController = nav
Najeeb ur Rehman
  • 403
  • 4
  • 11