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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28270282/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:38:17  来源:igfitidea点击:

What is the best way to check if a UIAlertController is already presenting?

iosuialertcontroller

提问by hidden-username

I have a tableview which, when loaded, each cell could possibly return an NSError, which I have chosen to display in a UIAlertController. Problem is I get this error in the console if multiple errors are returned.

我有一个 tableview,加载时,每个单元格都可能返回一个 NSError,我选择在 UIAlertController 中显示它。问题是如果返回多个错误,我会在控制台中收到此错误。

Warning: Attempt to present UIAlertController: 0x14e64cb00 on MessagesMasterVC: 0x14e53d800 which is already presenting (null)

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

Ideally, I would ideally like to handle this in my UIAlertController extension method.

理想情况下,我希望在我的 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
}

Based on matt's answer, I changed the extension to a UIViewController extension, its much cleaner and saves lots of presentViewController code.

根据马特的回答,我将扩展更改为 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)
    }
}

回答by matt

It is not the UIAlertController that is "already presenting", it is MessagesMasterVC. A view controller can only present one other view controller at a time. Hence the error message.

“已经呈现”的不是 UIAlertController,而是 MessagesMasterVC。一个视图控制器一次只能呈现一个其他的视图控制器。因此出现错误消息。

In other words, if you have told a view controller to presentViewController:..., you cannot do that again until the presented view controller has been dismissed.

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

You can ask the MessagesMasterVC whether it is already presenting a view controller by examining its presentedViewController. If not nil, do not tell it to presentViewController:...- it is already presenting a view controller.

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

回答by Ben

if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {

      // UIAlertController is presenting.Here

}

回答by LukeSideWalker

Well, the suggested solutions above has an essential problem from my point of view:

好吧,从我的角度来看,上面建议的解决方案有一个基本问题:

If you ask your ViewController, whether the attribute 'presentedViewController' is nil and the answer is false, you can't come to the conclusion, that your UIAlertController is already presented. It could be any presented ViewController, e.g. a popOver. So my suggestion to surely check, whether the Alert is already on the screen is the following (cast the presentedViewController as a UIAlertController):

如果你问你的 ViewController,属性 'presentedViewController' 是否为 nil 并且答案是否定的,你不能得出结论,你的 UIAlertController 已经被呈现。它可以是任何呈现的 ViewController,例如 popOver。所以我的建议是确定检查警报是否已经在屏幕上如下(将presentedViewController 转换为UIAlertController):

if self.presentedViewController == nil {
   // do your presentation of the UIAlertController
   // ...
} else {
   // either the Alert is already presented, or any other view controller
   // is active (e.g. 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, e.g. a PopOver")
      }
  }

}

}

回答by biomiker

Here's a solution I use in Swift 3. It is a function that shows an alert to the user, and if you call it multiple times before the user has dismissed the alert, it will add the new alert text to the alert that's already being presented. If some other view is being presented, the alert will not appear. Not all will agree with that behavior, but it works well for simple situations.

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

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)
    }
}

回答by Ravi

We can simply check if any view controller is presented.

我们可以简单地检查是否存在任何视图控制器。

if presented then check if it is kind of UIAlertController .

如果出现则检查它是否是 UIAlertController 。

    id alert = self.presentedViewController;

    if (alert && [alert isKindOfClass:[UIAlertController class]]) 
      {
           *// YES UIAlertController is already presented*
      }
    else
       {
        // UIAlertController is not presented OR visible.
       }

回答by Hope

I used that to detect and remove and alert.

我用它来检测、删除和警报。

First we create an alert with following function.

首先,我们创建一个具有以下功能的警报。

 var yourAlert :UIAlertController!

 func useYouAlert (header: String, info:String){


    yourAlert = UIAlertController(title:header as String, message: info as String, preferredStyle: UIAlertControllerStyle.alert)



    let okAction = UIAlertAction(title: self.langText[62]as String, style: UIAlertActionStyle.default) { (result : UIAlertAction) -> Void in
        print("OK") 

    }


    yourAlert.addAction(okAction)
    self.present(yourAlert.addAction, animated: true, completion: nil)

}

And in some other part of your code

在代码的其他部分

    if yourAlert != nil {

      yourAlert.dismiss(animated: true, completion: nil)

    }

回答by Shahid Aslam

For latest Swift language you can use following:

对于最新的 Swift 语言,您可以使用以下内容:

var alert = presentedViewController

if alert != nil && (alert is UIAlertController) {
    // YES UIAlertController is already presented*
} else {
    // UIAlertController is not presented OR visible.
}

回答by iOS Lifee

Swift 4.2+ Answer

斯威夫特 4.2+ 答案

if UIApplication.topViewController()!.isKind(of: UIAlertController.self) { 
            print("UIAlertController is presented")}

For those who don't know how to get top most Viewcontroller

对于那些不知道如何获得最顶层 Viewcontroller 的人

extension UIApplication {


public class func topViewController(_ base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
    if let nav = base as? UINavigationController {
        return topViewController(nav.visibleViewController)
    }
    if let tab = base as? UITabBarController {
        if let selected = tab.selectedViewController {
            return topViewController(selected)
        }
    }
    if let presented = base?.presentedViewController {
        return topViewController(presented)
    }
    return base
}}

Swift 5+ Answer'keyWindow'was deprecated in iOS 13.0 suggested edit

Swift 5+ Answer 'keyWindow'在 iOS 13.0建议编辑中被弃用

if UIApplication.topViewController()!.isKind(of: UIAlertController.self) { 
            print("UIAlertController is presented")}

For those who don't know how to get top most Viewcontroller

对于那些不知道如何获得最顶层 Viewcontroller 的人

extension UIApplication {


public class func topViewController(_ base: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
    if let nav = base as? UINavigationController {
        return topViewController(nav.visibleViewController)
    }
    if let tab = base as? UITabBarController {
        if let selected = tab.selectedViewController {
            return topViewController(selected)
        }
    }
    if let presented = base?.presentedViewController {
        return topViewController(presented)
    }
    return base
}}

回答by Faiz Ul Hassan

Dismiss the current controller and present the alert controller like

关闭当前控制器并呈现警报控制器,例如

 func alert(_ message:String) {
  let alert = UIAlertController(title: "Error!", message: message, preferredStyle: .alert)
  alert.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
  self.dismiss(animated: false, completion: nil)
  self.present(alert, animated: true,completion: nil)
    }

回答by Thierry G.

you can test - in a single line - if an alert is already presented:

您可以测试 - 在一行中 - 如果已经出现警报:

if self.presentedViewController as? UIAlertController != nil {
    print ("alert already presented")
}