尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)

Posted

技术标签:

【中文标题】尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)【英文标题】:Attempt to present UIAlertController whose view is not in the window hierarchy (Swift 3/Xcode 8) 【发布时间】:2017-09-10 14:39:30 【问题描述】:

我正在尝试创建一个应用程序,并且我想在出现登录错误或用户忘记输入用户名和/或密码时显示警报。但是,我总是收到此警告:

警告:尝试在 谁的视野不在窗内 等级制度!

我已经尝试了在这里找到的其他解决方案,但我仍然无法修复它。这是我的代码:

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)

            


        )

    


更新:这是整个视图控制器

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


【问题讨论】:

您可能在viewDidLoad 或其他地方调用createAlert。您能否添加您的整个视图控制器代码? @PranavKasetti 我已经用整个视图控制器代码更新了我的帖子 好的。您使用 segue 导航到哪个视图控制器? @PranavKasetti 到标签栏控制器视图 为什么self.dismiss(animated: true, completion: nil) 在你的UIAlertAction 的完成处理程序中?如果您将完成处理程序声明为 nilself 是指在此上下文中显示警报的视图控制器,则警报会自动解除,因此您不会像那样解除警报。 【参考方案1】:

首先创建UIAlertController这样一个属性。

var alertController: UIAlertController?

您必须像这样在 viewDidLoad() 中添加它:

override func viewDidLoad() 
    super.viewDidLoad()

    self.alertController = UIAlertController(title: "Alert", message: "Not images yet", preferredStyle: .alert)
    self.alertController?.addAction(UIAlertAction(title: "Close", style: .default))
    view.addSubview((alertController?.view)!)


因此,当您按下 signInButton 并且登录不正确时,您必须调用。

@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 

            self.presentedViewController?.present(self.alertController!, animated: true, completion: nil)
        

【讨论】:

【参考方案2】:

每当我们试图在任何闭包中呈现 UIAlertController 时,我们都应该在主线程上调用它,例如:

DispatchQueue.main.async  [weak self] in
    self?.createAlert(title: "Sign in error", message: displayErrorMessage)

【讨论】:

【参考方案3】:

Swift 3

试试这个代码
func displayMyAlertMessageError(userMessage:String, titleHead: String)
    //define displyMyAlertMessage.

    let MyAlert = UIAlertController(title: titleHead, message: userMessage, preferredStyle:UIAlertControllerStyle.alert);
    let okAction = UIAlertAction(title: "Okay", style: UIAlertActionStyle.default, handler: nil);MyAlert.addAction(okAction);
    self.present(MyAlert,animated:true,completion:nil);


@IBAction func signInPressed(_ sender: Any) 

  if (usernameTextField.text?.isEmpty) || (passwordTextField.text?.isEmpty)
    
      createAlert(title: "Error in form", message: "Please enter an email and password.")
    
  else 
    
      //Your code here
    

【讨论】:

【参考方案4】:

将您的 createAlert 方法更改为此,

func createAlert(title: String, message: String, controller: UIViewController) 

        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)

        alert.addAction(UIAlertAction(title: "OK", style: .default, handler:  (action) in

            self.dismiss(animated: true, completion: nil)

        ))
        controller.present(alert, animated: true, completion: nil)

    

然后像这样创建警报,

self.createAlert(title: "Sign in error", message: "Please try again later.", controller: self)

这可能会解决您的问题。

【讨论】:

谢谢!但它仍然在我的调试区域显示相同的警告:(

以上是关于尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

尝试呈现其视图不在窗口层次结构中的 UIAlertController (Swift 3/Xcode 8)

警告:尝试在其视图不在窗口层次结构中的 ViewController 上呈现 ViewController (w/UIAlertController)

如何解决此错误“警告:尝试呈现其视图不在窗口层次结构中”?