I'm trying to create an app and I want to show an alert when there is a login error or if the user forget to enter a username and/or password. However, I always get this warning:
Warning: Attempt to present on whose view is not in the window hierarchy!
I have tried the other solutions I found here but I still can't fix it. Here's my code:
func createAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
@IBAction func signInPressed(_ sender: Any) {
if usernameTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error in form", message: "Please enter an email and password.")
} else {
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: { (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil {
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Sign in error", message: displayErrorMessage)
} else {
print("Logged in")
self.performSegue(withIdentifier: "toSignIn", sender: self)
}
})
}
}
UPDATE: Here's the whole view controller
class ViewController: UIViewController {
@IBOutlet var usernameTextField: UITextField!
@IBOutlet var passwordTextField: UITextField!
func createAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
@IBAction func signInPressed(_ sender: Any) {
if usernameTextField.text == "" || passwordTextField.text == "" {
createAlert(title: "Error in form", message: "Please enter an email and password.")
} else {
var activityIndicator = UIActivityIndicatorView()
activityIndicator = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
activityIndicator.center = self.view.center
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
PFUser.logInWithUsername(inBackground: usernameTextField.text!, password: passwordTextField.text!, block: { (user, error) in
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
if error != nil {
var displayErrorMessage = "Please try again later."
let error = error as NSError?
if let errorMessage = error?.userInfo["error"] as? String {
displayErrorMessage = errorMessage
}
self.createAlert(title: "Sign in error", message: displayErrorMessage)
} else {
print("Logged in")
self.performSegue(withIdentifier: "toSignIn", sender: self)
}
})
}
}
override func viewDidAppear(_ animated: Bool) {
if PFUser.current() != nil {
performSegue(withIdentifier: "toSignIn", sender: self)
}
self.tabBarController?.tabBar.isHidden = true
}
override func viewDidLoad() {
super.viewDidLoad()
}
createAlert
inviewDidLoad
or somewhere else. Could you please add your whole view controller code? – Pranav Kasettiself.dismiss(animated: true, completion: nil)
in the completion handler of yourUIAlertAction
? The alert is automatically dismissed if you declare the completion handler asnil
andself
refers to the view controller the alert is presented from in this context, so you are not dismissing the alert like that. – Dávid Pásztor