【问题标题】:Attempt to present UIAlertController whose view is not in the window hierarchy - Swift Error尝试呈现其视图不在窗口层次结构中的 UIAlertController - Swift 错误
【发布时间】:2018-03-07 12:12:23
【问题描述】:

我正在尝试创建警报,因此当用户注册然后想要重新登录时,如果密码错误,他们会收到警告,因为此时它只是执行 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)
        }
     }
    }
  }
}

【问题讨论】:

    标签: ios swift firebase firebase-authentication uialertcontroller


    【解决方案1】:

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

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

    【讨论】:

    • 你是个传奇!谢谢,但很烦人,这个微不足道的事情就是错误!
    • 不客气!很高兴我能帮上忙。您介意将答案标记为正确吗?干杯:)
    【解决方案2】:

    您在SignInViewController 上显示UIAlertController,所以当时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.")
        }
    }
    //###############################################
    
    }
    

    【讨论】:

    • 我想我理解你的来历,但由于我目前正在学习 Swift,我不确定如何实现你所说的。抱歉,您能多指点我一下吗?
    • 抱歉刚刚试了,还是报同样的错误
    • 尝试在其视图不在窗口层次结构中的 上呈现
    • 是的,我认为我以正确的方式使用它,您能否使用我的所有代码进行编辑,以便我查看它是否正确使用?
    • 对不起,伙计,将它粘贴到我之前的代码中并得到同样的错误......我真的很难理解它是什么
    【解决方案3】:

    在主要活动中展示它:

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

    【讨论】:

    • 顺便说一句,这不是问题!!
    猜你喜欢
    • 2017-07-27
    • 2018-06-06
    • 2023-03-31
    • 1970-01-01
    • 2015-06-04
    • 2020-08-07
    • 2016-11-29
    • 1970-01-01
    • 2014-06-01
    相关资源
    最近更新 更多