尝试呈现其视图不在窗口层次结构中的UIAlertController - Swift Error

时间:2018-03-07 12:12:23

标签: ios swift firebase firebase-authentication uialertcontroller

我正在尝试创建一个警报,因此当用户注册然后想要重新登录时,如果密码错误则可以发出警告,因为此时它只执行segue并且尝试警报失败。我正在使用Firebase,因此在注册时输入firebase的密码应该是用户登录的密码。

import Foundation
import UIKit
import Firebase

class SignInViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var EmailAddressTextField: UITextField!
@IBOutlet weak var PasswordTextField: UITextField!

// Do any additional setup after loading the view.
override func viewDidLoad() {
    super.viewDidLoad()

    EmailAddressTextField.delegate = self
    PasswordTextField.delegate = self
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
}

@IBAction func LogInButton(_ sender: Any) {
if (EmailAddressTextField.text != "" && PasswordTextField.text != ""){
Auth.auth().signIn(withEmail: EmailAddressTextField.text!, password: PasswordTextField.text!) { user, error in
    if error == nil {
        self.performSegue(withIdentifier: "LogInSegue", sender: nil)
    } else {
        let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
        }
     }
    }
  }
}

3 个答案:

答案 0 :(得分:1)

您正在UIAlertController上展示SignInViewController,因此当时SignInViewController不在导航堆栈中。

因此,当您在此时展示UIAlertController时,请检查self.navigationController?.viewControllers并验证它是否在堆栈中。

例如。

//check before self.presnt...
print(self.navigationController?.viewControllers)

因此,您需要确保在将视图控制器呈现在另一个必须位于导航堆栈中的视图控制器时,否则您将在日志中收到此消息。

  

尝试呈现视图不在窗口层次结构中的UIAlertController

使用以下函数在根视图控制器上显示警报

 func showAlert(title: String, msg: String, actions:[UIAlertAction]?) {

    var actions = actions
    let alertVC = UIAlertController(title: title, message: msg, preferredStyle: .alert)

    if actions == nil {
        actions = [UIAlertAction(title: "OK", style: .default, handler: nil)]
    }

    for action in actions! {
        alertVC.addAction(action)
    }

    if let rootVC = UIApplication.shared.delegate?.window??.rootViewController {
        rootVC.present(alertVC, animated: true, completion: nil)
    } else {
        print("Root view controller is not set.")
    }
}

用法

self.showAlert(title: "My App", msg: "your message", actions: nil)

你需要在你的代码中使用它......

class SignInViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var EmailAddressTextField: UITextField!
@IBOutlet weak var PasswordTextField: UITextField!

// Do any additional setup after loading the view.
override func viewDidLoad() {
    super.viewDidLoad()

    EmailAddressTextField.delegate = self
    PasswordTextField.delegate = self
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
}

@IBAction func LogInButton(_ sender: Any) {
    if (EmailAddressTextField.text != "" && PasswordTextField.text != ""){
        Auth.auth().signIn(withEmail: EmailAddressTextField.text!, password: PasswordTextField.text!) { user, error in
            if error == nil {
                self.performSegue(withIdentifier: "LogInSegue", sender: nil)
            } else {
//                    let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
//                    let action = UIAlertAction(title: "OK", style: .default, handler: nil)
//                    alert.addAction(action)
//                    self.present(alert, animated: true, completion: nil)

                //use like this...
                self.showAlert(title: "Error", msg: "Enter a correct email and password", actions: nil)
            }

        }
    }
}

//###############################################
func showAlert(title: String, msg: String, actions:[UIAlertAction]?) {

    var actions = actions
    let alertVC = UIAlertController(title: title, message: msg, preferredStyle: .alert)

    if actions == nil {
        actions = [UIAlertAction(title: "OK", style: .default, handler: nil)]
    }

    for action in actions! {
        alertVC.addAction(action)
    }

    if let rootVC = UIApplication.shared.delegate?.window??.rootViewController {
        rootVC.present(alertVC, animated: true, completion: nil)
    } else {
        print("Root view controller is not set.")
    }
}
//###############################################

}

答案 1 :(得分:1)

只是想跟你检查一下,因为上面的描述有点不清楚。当您输入错误的电子邮件/密码组合时,您的应用程序是否仍然执行“LogInSegue”(以及未能显示警报)?

如果是这样,听起来你可能已经将你的segue连接到UIButton而不是UIViewController。 要检查这一点,请单击Storyboard中的segue,查看是否突出显示了UIButton。 如果是,则删除此segue并按照以下说明从视图控制器连接新的segue:

Add segue to view controller

答案 2 :(得分:0)

在主要活动中展示:

dispatch_async(dispatch_get_main_queue(), ^{
   let alert = UIAlertController(title: "Error", message: "Enter a correct email and password", preferredStyle: .alert)
   let action = UIAlertAction(title: "OK", style: .default, handler: nil)
   alert.addAction(action)
   self.present(alert, animated: true, completion: nil)
});