Каков наилучший способ проверить, уже ли отображается 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)
}
}
Ответы
Ответ 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()