Подтвердить что ты не робот

Каков наилучший способ проверить, уже ли отображается UIAlertController?

У меня есть табличное представление, которое при загрузке каждая ячейка могла бы вернуть NSError, который я выбрал для отображения в UIAlertController. Проблема в том, что я получаю эту ошибку в консоли, если возвращаются несколько ошибок.

Предупреждение: попытка представить UIAlertController: 0x14e64cb00 на MessageMasterVC: 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, его намного чище и экономит много кода currentViewController.

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

Ответ 1

Это не UIAlertController, который уже "представляет", это MessageMasterVC. Контроллер вида может одновременно отображать только один контроллер просмотра. Отсюда сообщение об ошибке.

Другими словами, если вы сказали контроллеру вида presentViewController:..., вы не сможете сделать это до тех пор, пока представленный контроллер представления не будет уволен.

Вы можете спросить MessageMasterVC, будет ли он уже представлять контроллер представления, исследуя его presentedViewController. Если не nil, не указывайте его на presentViewController:... - он уже представляет контроллер вида.

Ответ 2

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

      // UIAlertController is presenting.Here

}

Ответ 3

Итак, предлагаемые решения выше имеют существенную проблему с моей точки зрения:

Если вы спросите своего ViewController, является ли атрибут "ПредставленныйViewController" равным нулю, а ответ ложным, вы не можете прийти к выводу, что ваш UIAlertController уже представлен. Это может быть любой представленный ViewController, например. popOver. Поэтому мое предложение наверняка проверить, является ли оповещение уже на экране следующим: (передайте представленныйViewController как 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")
      }
  }

}

Ответ 4

Здесь решение, которое я использую в 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)
    }
}

Ответ 5

Мы можем просто проверить, представлен ли какой-либо контроллер представления.

если представлено, проверьте, является ли это своего рода UIAlertController.

    id alert = self.presentedViewController;

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

Ответ 6

Эта категория может автоматически управлять всеми модальными контроллерами, включая UIAlertController.

UIViewController + JCPresentQueue.h

Ответ 7

Я использовал это, чтобы обнаружить и удалить и предупредить.

Сначала мы создаем оповещение со следующей функцией.

 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)

}

И в какой-то другой части вашего кода

    if yourAlert != nil {

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

    }

Ответ 8

Для последнего языка Swift вы можете использовать следующее:

var alert = presentedViewController

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

Ответ 9

Свифт 4. 2+ Ответ

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

Для тех, кто не знает, как получить самый верхний 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
}}

Ответ 10

Отключить текущий контроллер и представить контроллер предупреждений как

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

Ответ 11

Это случилось со мной, когда я пытался обрабатывать UI elements в другом потоке, чем Main Thread. У меня была такая же проблема, когда я показал предупреждение в блоке массива фильтров. Когда я вывел из блока фильтра предупреждающий сигнал, предупреждение с консоли исчезло.

Ответ 12

Просто отпустите текущий контроллер и представите тот, который вы хотите то есть.

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

self.displayAlertController()