ios AlertController 不在窗口层次结构中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29257670/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:20:19  来源:igfitidea点击:

AlertController is not in the window hierarchy

iosswiftstoryboarduialertviewuialertcontroller

提问by wtznc

I've just created a Single View Application project with ViewController class. I would like to show a UIAlertController from a function which is located inside my own class.

我刚刚用 ViewController 类创建了一个单一视图应用程序项目。我想从位于我自己的类中的函数中显示 UIAlertController。

Here is my class with an alert.

这是我的班级,有警报。

class AlertController: UIViewController {
     func showAlert() { 
         var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
         self.presentViewController(alert, animated: true, completion: nil)
     }
}

Here is ViewController which executes the alert.

这是执行警报的 ViewController。

class ViewController: UIViewController {
   override func viewDidLoad() {
       super.viewDidLoad()  
   }

   @IBAction func showAlertButton(sender: AnyObject) {
       var alert = AlertController()
       alert.showAlert()
   }
}

This is what I get instead of a beautiful alert.

这是我得到的,而不是一个美丽的警报。

Warning: Attempt to present UIAlertController: 0x797d2d20 on Sprint1.AlertController: 0x797cc500 whose view is not in the window hierarchy!

警告:尝试在 Sprint1.AlertController: 0x797cc500 上显示 UIAlertController: 0x797d2d20 其视图不在窗口层次结构中!

What should I do?

我该怎么办?

回答by Skoua

If you're instancing your UIAlertControllerfrom a modal controller, you need to do it in viewDidAppear, not in viewDidLoador you'll get an error.

如果您是UIAlertController从模态控制器实例化您的,则需要在 中进行viewDidAppear,而不是在 中,viewDidLoad否则会出现错误。

Here's my code (Swift 4):

这是我的代码(Swift 4):

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

    let alertController = UIAlertController(title: "Foo", message: "Bar", preferredStyle: .alert)

    alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    present(alertController, animated: true, completion: nil)
}

回答by Sulthan

Let's look at your view hierarchy. You have a ViewController. Then you are creating an AlertController, you are not adding it to your hierarchy and you are calling an instance method on it, that attempts to use the AlertControlleras presenting controller to show just another controller (UIAlertController).

让我们看看您的视图层次结构。你有一个ViewController. 然后您创建一个AlertController,您没有将其添加到您的层次结构中,而是在其上调用一个实例方法,该方法尝试使用AlertController作为呈现控制器来仅显示另一个控制器 ( UIAlertController)。

+ ViewController
    + AlertController (not in hierarchy)
        + UIAlertController (cannot be presented from AlertController)

To simplify your code

简化您的代码

class ViewController: UIViewController {
   override func viewDidLoad() {
       super.viewDidLoad()  
   }

   @IBAction func showAlertButton(sender: AnyObject) {
       var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
       self.presentViewController(alert, animated: true, completion: nil)
   }
}

This will work.

这将起作用。

If you need the AlertControllerfor something, you will have to add it to the hierarchy first, e.g. using addChildViewControlleror using another presentViewControllercall.

如果您需要AlertController某个东西,您必须首先将它添加到层次结构中,例如使用addChildViewController或使用另一个presentViewController调用。

If you want the class to be just a helper for creating alert, it should look like this:

如果您希望该类只是创建警报的助手,则它应该如下所示:

class AlertHelper {
    func showAlert(fromController controller: UIViewController) { 
        var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
        controller.presentViewController(alert, animated: true, completion: nil)
    }
}

called as

称为

 var alert = AlertHelper()
 alert.showAlert(fromController: self)

回答by Varun Naharia

You can use below function to call alert from any where just include these method in AnyClass

您可以使用以下函数从任何地方调用警报,只需在 AnyClass 中包含这些方法

class func topMostController() -> UIViewController {
        var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController
        while ((topController?.presentedViewController) != nil) {
            topController = topController?.presentedViewController
        }
        return topController!
    }

    class func alert(message:String){
        let alert=UIAlertController(title: "AppName", message: message, preferredStyle: .alert);
        let cancelAction: UIAlertAction = UIAlertAction(title: "OK", style: .cancel) { action -> Void in

        }
        alert.addAction(cancelAction)
        AnyClass.topMostController().present(alert, animated: true, completion: nil);
    }

Then call

然后打电话

AnyClass.alert(message:"Your Message")

回答by Mitsuaki Ishimoto

Write the following 3 lines, all we need to do is this.

写下面3行,我们需要做的就是这个。

Swift 3.0

斯威夫特 3.0

private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
     UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
  }

Swift 2.0

斯威夫特 2.0

  private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
     UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: flag, completion: completion)
  }

回答by Prajeet Shrestha

If you want to create a separate class for displaying alert like this, subclass NSObject not UIViewController.

如果你想创建一个单独的类来显示这样的警报,子类 NSObject 而不是 UIViewController。

And pass the ViewControllers reference from which it is initiated, to the showAlert function so that you can present alert view there.

并将启动它的 ViewControllers 引用传递给 showAlert 函数,以便您可以在那里显示警报视图。

回答by user462990

Here is the code of an UIAlertController in a Utility.swift class (not a UIViewController) in Swift3, Thanks Mitsuaki!

这是 Swift3 中 Utility.swift 类(不是 UIViewController)中 UIAlertController 的代码,谢谢 Mitsuaki!

private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
    UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
func warningAlert(title: String, message: String ){
    let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
    alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler:  { (action) -> Void in
    }))        
 //   self.present(alert, animated: true, completion: nil)
    presentViewController(alert: alert, animated: true, completion: nil)
}

回答by Johnny Rockex

It helped me to stick a slight delay between the viewDidLoad method and firing the alert method:

它帮助我在 viewDidLoad 方法和触发警报方法之间稍微延迟:

   [self performSelector:@selector(checkPhotoPermission) withObject:nil afterDelay:0.1f];

回答by Pedro Trujillo

This worked for me:

这对我有用:

- (UIViewController *)topViewController{
  return [self topViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}

- (UIViewController *)topViewController:(UIViewController *)rootViewController
{
  if (rootViewController.presentedViewController == nil) {
    return rootViewController;
  }

  if ([rootViewController.presentedViewController isMemberOfClass:[UINavigationController class]]) {
    UINavigationController *navigationController = (UINavigationController *)rootViewController.presentedViewController;
    UIViewController *lastViewController = [[navigationController viewControllers] lastObject];
    return [self topViewController:lastViewController];
  }

  UIViewController *presentedViewController = (UIViewController *)rootViewController.presentedViewController;
  return [self topViewController:presentedViewController];
}

Implementation:

执行:

UIViewController * topViewController = [self topViewController];

Using with alert:

与警报一起使用:

[topViewController presentViewController:yourAlert animated:YES completion:nil];

You can send an alert from any class in your app (that uses UIKit: #import <UIKit/UIKit.h>)

您可以从应用程序中的任何类(使用 UIKit: #import <UIKit/UIKit.h>)发送警报

Source here.

来源在这里。