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 чей вид не является в иерархии окон!



Что мне делать?

605   7  

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

    Ничего не найдено.