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)
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