AlertController не находится в иерархии окон
Я только что создал проект приложения Single 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, представление которого не находится в иерархии окон!
Что я должен делать?
Ответы
Ответ 1
Если вы UIAlertController
свой 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)
}
Ответ 2
Посмотрите на свою иерархию просмотров. У вас есть 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)
Ответ 3
Вы можете использовать функцию ниже, чтобы вызывать оповещение от любого, где просто включить этот метод в 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")
Ответ 4
Напишите следующие 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)
}
Ответ 5
Если вы хотите создать отдельный класс для отображения такого предупреждения, подкласс NSObject не UIViewController.
И передайте ссылку ViewControllers, с которой она была инициирована, в функцию showAlert, чтобы вы могли видеть там предупреждение.
Ответ 6
Вот код UIAlertController в классе Utility.swift(не UIViewController) в Swift3, спасибо 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)
}
Ответ 7
Это помогло мне вставить небольшую задержку между методом viewDidLoad и запуском метода alert:
[self performSelector:@selector(checkPhotoPermission) withObject:nil afterDelay:0.1f];
Ответ 8
Это сработало для меня:
- (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];
}
Реализация:
UIViewController * topViewController = [self topViewController];
Использование с предупреждением:
[topViewController presentViewController:yourAlert animated:YES completion:nil];
Вы можете отправить предупреждение из любого класса в вашем приложении (которое использует UIKit: #import <UIKit/UIKit.h>
)
Источник здесь.