J'ai une table qui, une fois chargée, chaque cellule peut éventuellement renvoyer une erreur NSError, que j'ai choisi d'afficher dans un UIAlertController. Le problème est que je reçois cette erreur dans la console si plusieurs erreurs sont renvoyées.
Avertissement: Tentative de présenter UIAlertController: 0x14e64cb00 sur MessagesMasterVC: 0x14e53d800 qui présente déjà (null)
Idéalement, j'aimerais idéalement gérer cela dans ma méthode d'extension 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
}
Sur la base de la réponse de matt, j'ai changé l'extension en une extension UIViewController, qui est beaucoup plus propre et enregistre beaucoup de code 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)
}
}
Ce n'est pas le UIAlertController qui "présente déjà", c'est MessagesMasterVC. Un contrôleur de vue ne peut présenter qu'un seul autre contrôleur de vue à la fois. D'où le message d'erreur.
En d'autres termes, si vous avez dit à un contrôleur de vue de presentViewController:...
, vous ne pouvez pas le refaire tant que le contrôleur de vue présenté n’a pas été congédié.
Vous pouvez demander à MessagesMasterVC s'il présente déjà un contrôleur de vue en examinant son presentedViewController
. Sinon nil
, ne le dites pas à presentViewController:...
- il présente déjà un contrôleur de vue.
if ([self.navigationController.visibleViewController isKindOfClass:[UIAlertController class]]) {
// UIAlertController is presenting.Here
}
Eh bien, les solutions suggérées ci-dessus ont un problème essentiel de mon point de vue:
Si vous demandez à votre ViewController si l'attribut 'presentsViewController' est nul et si la réponse est fausse, vous ne pouvez en venir à la conclusion que votre UIAlertController est déjà présenté. Cela pourrait être n'importe quel ViewController présenté, par exemple. un popOver. Donc, ma suggestion de vérifier si l'alerte est déjà affichée est la suivante (transformez leViewController en 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")
}
}
}
Voici une solution que j’utilise Swift 3. C’est une fonction qui affiche une alerte à l’utilisateur. Si vous l’appelez plusieurs fois avant que l’utilisateur ait ignoré l’alerte, elle ajoutera la nouvelle Texte d'alerte relatif à l'alerte déjà présentée. Si une autre vue est présentée, l'alerte n'apparaîtra pas. Tous ne seront pas d'accord avec ce comportement, mais cela fonctionne bien pour des situations simples.
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)
}
}
Nous pouvons simplement vérifier si un contrôleur de vue est présenté.
si présenté, vérifiez si c'est un peu UIAlertController.
id alert = self.presentedViewController;
if (alert && [alert isKindOfClass:[UIAlertController class]])
{
*// YES UIAlertController is already presented*
}
else
{
// UIAlertController is not presented OR visible.
}
Réponse de Swift 4.2+
if UIApplication.topViewController()!.isKind(of: UIAlertController.self) {
print("UIAlertController is presented")}
Pour ceux qui ne savent pas comment obtenir le top 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
}}
Fermez le contrôleur actuel et présentez-le comme suit:
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)
}
Je l'ai utilisé pour détecter et supprimer et alerter.
Nous créons d'abord une alerte avec la fonction suivante.
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)
}
Et dans une autre partie de votre code
if yourAlert != nil {
yourAlert.dismiss(animated: true, completion: nil)
}
vous pouvez tester - sur une seule ligne - si une alerte est déjà présentée:
if self.presentedViewController as? UIAlertController != nil {
print ("alert already presented")
}
Pour la dernière Swift, vous pouvez utiliser les éléments suivants:
var alert = presentedViewController
if alert != nil && (alert is UIAlertController) {
// YES UIAlertController is already presented*
} else {
// UIAlertController is not presented OR visible.
}
Cette catégorie peut gérer automatiquement tous les contrôleurs modaux inclus dans UIAlertController.