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
AlertController is not in the window hierarchy
提问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 UIAlertController
from a modal controller, you need to do it in viewDidAppear
, not in viewDidLoad
or 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 AlertController
as 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 AlertController
for something, you will have to add it to the hierarchy first, e.g. using addChildViewController
or using another presentViewController
call.
如果您需要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>
)发送警报