检查UIAlertController是否已经呈现的最佳方法是什么?

我有一个tableview,加载时,每个单元格可能会返回一个NSError,我已经select显示在一个UIAlertController。 问题是我得到这个错误在控制台中,如果多个错误返回。

警告:尝试在MessagesMasterVC上显示UIAlertController:0x14e64cb00:0x14e53d800已经呈现(null)

理想情况下,我最好喜欢在我的UIAlertController扩展方法中处理这个。

class func simpleAlertWithMessage(message: String!) -> UIAlertController { let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert) let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil) alertController.addAction(cancel) return alertController } 

基于马特的答案,我将扩展名更改为一个UIViewController扩展,它更干净,并节省了很多presentViewController代码。

  func showSimpleAlertWithMessage(message: String!) { let alertController = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert) let cancel = UIAlertAction(title: "Ok", style: .Cancel, handler: nil) alertController.addAction(cancel) if self.presentedViewController == nil { self.presentViewController(alertController, animated: true, completion: nil) } } 

这不是UIAlertController是“已经呈现”,它是MessagesMasterVC。 视图控制器一次只能呈现另一个视图控制器。 因此,错误消息。

换句话说,如果你已经告诉一个视图控制器presentViewController:... ,你不能再这样做,直到视图控制器已被解雇。

您可以通过检查其presentedViewController来询问MessagesMasterVC是否已经呈现视图控制器。 如果不是nil ,不要告诉它presentViewController:... – 它已经呈现一个视图控制器。

 if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) { // UIAlertController is presenting.Here } 

那么,从我的angular度来看,上面提出的解决scheme确实存在一个基本问题:

如果你问你的ViewController,那么“presentedViewController”属性是零,答案是错误的,你不能得出结论,你的UIAlertController已经出现了。 它可以是任何呈现的ViewController,例如popOver。 所以我的build议,一定要检查,警报是否已经在屏幕上是以下(作为一个UIAlertController转换presentViewController):

 if self.presentedViewController == nil { // do your presentation of the UIAlertController // ... } else { // either the Alert is already presented, or any other view controller // is active (eg a PopOver) // ... let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController? if thePresentedVC != nil { if let thePresentedVCAsAlertController : UIAlertController = thePresentedVC as? UIAlertController { // nothing to do , AlertController already active // ... print("Alert not necessary, already on the screen !") } else { // there is another ViewController presented // but it is not an UIAlertController, so do // your UIAlertController-Presentation with // this (presented) ViewController // ... thePresentedVC!.presentViewController(...) print("Alert comes up via another presented VC, eg a PopOver") } } 

}

这个类别可以自动pipe理UIAlertController的所有模态控制器。

的UIViewController + JCPresentQueue.h

简单地解雇目前的控制器,并呈现你想要的,即

self.dismiss(animated: false, completion: nil)

self.displayAlertController()

这里是我在Swift 3中使用的一个解决scheme。它是一个向用户显示警报的函数,如果在用户解除警报之前多次调用它,它会将新的警报文本添加到已经呈现的警报中。 如果出现其他视图,则不会显示警报。 并不是所有的人都会同意这种行为,但是对于简单的情况,这种方式很好。

 extension UIViewController { func showAlert(_ msg: String, title: String = "") { if let currentAlert = self.presentedViewController as? UIAlertController { currentAlert.message = (currentAlert.message ?? "") + "\n\nUpdate:\(title): \(msg)" return } // create the alert let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert) alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) // show the alert self.present(alert, animated: true, completion: nil) } }