AlertController не находится в иерархии окон
Я только что создал один проект приложения View с классом ViewController. Я хотел бы показать UIAlertController из функции, которая находится внутри моего собственного класса.
Вот мой класс с предупреждением.
class AlertController: UIViewController {
func showAlert() {
var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert)
self.presentViewController(alert, animated: true, completion: nil)
}
}
Здесь находится ViewController, который выполняет оповещение.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func showAlertButton(sender: AnyObject) {
var alert = AlertController()
alert.showAlert()
}
}
Это то, что я получаю вместо красивой тревоги.
предупреждение: попытка представить UIAlertController: 0x797d2d20 на Sprint1.AlertController: 0x797cc500 чей вид не является в иерархии окон!
Что мне делать?
7 ответов:
Давайте посмотрим на вашу иерархию представлений. У вас есть
ViewController. Затем вы создаетеAlertController, вы не добавляете его в свою иерархию и вызываете метод экземпляра на нем, который пытается использоватьAlertControllerкак представляющий контроллер, чтобы показать просто другой контроллер (UIAlertController).+ ViewController + AlertController (not in hierarchy) + UIAlertController (cannot be presented from AlertController)Для упрощения кода
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) } }Это сработает.
Если вам нужен
AlertControllerдля чего-то, вам придется сначала добавить его в иерархию, например, используяaddChildViewControllerили используя другойpresentViewControllerвызов.Если вы хотите, чтобы класс был просто помощником для создания предупреждения, он должен выглядеть следующим образом:
class AlertHelper { func showAlert(fromController controller: UIViewController) { var alert = UIAlertController(title: "abc", message: "def", preferredStyle: .Alert) controller.presentViewController(alert, animated: true, completion: nil) } }Называется
var alert = AlertHelper() alert.showAlert(fromController: self)
Если вы создаете экземпляр вашего
UIAlertControllerиз модального контроллера, вам нужно сделать это вviewDidAppear, а не вviewDidLoad, иначе вы получите ошибку.Вот мой код (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) }
Напишите следующие 3 строки, все, что нам нужно сделать, это сделать следующее.
Swift 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
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void { UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(alert, animated: flag, completion: completion) }
Вы можете использовать приведенную ниже функцию для вызова alert из любого места, где просто включите этот метод в 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); }Затем вызовите
AnyClass.alert(message:"Your Message")
Если вы хотите создать отдельный класс для отображения такого предупреждения, подкласс NSObject not UIViewController.
И передайте ссылку ViewControllers, из которой она инициируется, в функцию showAlert, чтобы вы могли представить там представление alert.
Вот код UIAlertController в утилите.swift class (не UIViewController) в Swift3, спасибо Мицуаки!
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) }
Это помогло мне установить небольшую задержку между методом viewDidLoad и запуском метода alert:
[self performSelector:@selector(checkPhotoPermission) withObject:nil afterDelay:0.1f];
Comments