I am new in Programming and swift, and I have tried to read some solutions in stack overflow, but to be honest I don't really grasp with the answer :(
I have 2 view controllers. a homeVC and a LoginVC. homeVC is my initial view controller. in viewDidLoad
I have firebase function that can check if the user has logged in before or not. if not, then the user will be send to loginVC. here is my simplified code in the HomeVC
import UIKit
import Firebase
class HomeVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// to check whether the user has already logged in or not
Auth.auth().addStateDidChangeListener { (auth, user) in
if user == nil {
let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)
}
}
print("user enter homeVC")
}
}
and here is my loginVC
import UIKit
import Firebase
import GoogleSignIn
class LoginVC : UIViewController, GIDSignInUIDelegate {
@IBOutlet weak var googleButton: GIDSignInButton!
@IBOutlet weak var emailButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// delegate declaration
GIDSignIn.sharedInstance().uiDelegate = self
}
@IBAction func googleButtonDidPressed(_ sender: Any) {
GIDSignIn.sharedInstance().signIn()
}
}
the app can perform as I expected. but there is a warning in my debugging area :
Warning: Attempt to present LoginVC: 0x7fc315714f40 on HomeVC: 0x7fc3155095c0 whose view is not in the window hierarchy!
of course the problem is in this lines of code
let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)
as far as I know, if the view is stacked in the layer of navigation controller, then if I want to move to another view controller I have to use perform segue
method.
But for this case, between homeVC and LoginVC are not stacked in the same navigation controller. so no hierarchy. thats why I use that line of code to move to another view controller (loginVC). but I don't understand why it is said "view is not in the window hierarchy!"
So what should I do to omit that warning?
Your LoginVC
is perfectly fine.
However, you need to change your HomeVC
as @Sh_Khan suggested and move the testing code from viewDidLoad
to viewDidAppear
:
import UIKit
import Firebase
class HomeVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// HomeVC.view was added to a view hierarchy
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// to check whether the user has already logged in or not
Auth.auth().addStateDidChangeListener { (auth, user) in
if user == nil {
let login = self.storyboard?.instantiateViewController(withIdentifier: "login") as! LoginVC
self.present(login, animated: true, completion: nil)
}
}
}
}
Explanation
Your viewDidLoad
method gets called before the viewController
gets presented, so it at that moment it cannot really present another view controller (since it itself is not presented), viewDidLoad
documentation:
Called after the controller's view is loaded into memory.
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView() method. You usually override this method to perform additional initialization on views that were loaded from nib files.
In that moment the viewController is not in the window hierarchy yet.
viewDidAppear
however gets called when the view
is presented and becomes a part of the window hierarchy, viewDidAppear
documentation:
Notifies the view controller that its view was added to a view hierarchy.
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
Don't forget to call super.viewDidAppear
during overriding it.