web-dev-qa-db-fra.com

Swift Affichage des meilleures pratiques d'affichage des alertes

J'ai plusieurs contrôleurs dans mon application qui nécessitent tous une validation, et lorsque la validation échoue, je veux afficher une alerte avec les erreurs. Existe-t-il un modèle de meilleure pratique/conception pour ce faire? Je pourrais simplement créer une fonction statique dans une classe Helper comme ceci:

static func displayAlert(message: String, buttonTitle: String, vc: UIViewController)
{
    let alertController = UIAlertController(title: "", message: message, preferredStyle: .Alert)

    let OKAction = UIAlertAction(title: buttonTitle, style: .Default, handler: nil)
    alertController.addAction(OKAction)

    vc.presentViewController(alertController, animated: true, completion: nil)
}

Mais alors je dois passer le contrôleur de vue ... ce qui semble être une mauvaise pratique. Je pourrais tirer une notification et l'observer, mais cela semble exagéré. Suis-je en train de réfléchir à cela, ou y a-t-il une façon plus acceptable de gérer quelque chose comme ça?

26
Ryan Bobrowski

J'ai fini par créer une extension pour UIViewController et y créer la fonction d'alerte:

extension UIViewController {

  func alert(message: String, title: String = "") {
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    let OKAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alertController.addAction(OKAction)
    self.presentViewController(alertController, animated: true, completion: nil)
  }

}
52
Ryan Bobrowski

Swift 4

Voilà, je le voulais donc j'ai fait une extension complète. Créez donc un nouveau fichier Swift dans votre projet, nommez-le comme vous le souhaitez à côté, placez le code suivant.

import UIKit

extension UIViewController {

    func presentAlertWithTitle(title: String, message: String, options: String..., completion: @escaping (Int) -> Void) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        for (index, option) in options.enumerated() {
            alertController.addAction(UIAlertAction.init(title: option, style: .default, handler: { (action) in
                completion(index)
            }))
        }
        self.present(alertController, animated: true, completion: nil)
    }
}

Ensuite, l'utiliser que tant de gens ne montrent pas réellement, ce qui peut créer de la confusion pour un débutant comme moi.

presentAlertWithTitle(title: "Test", message: "A message", options: "1", "2") { (option) in
    print("option: \(option)")
    switch(option) {
        case 0:
            print("option one")
            break
        case 1:
            print("option two")
        default:
            break
    }
}
25
Sigex

Comme réponse originale de itstrueimryan à https://stackoverflow.com/a/30714429/682218

Mise à jour pour Swift 3:

extension UIViewController {

    func alert(message: String, title: String = "") {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let OKAction = UIAlertAction(title: "OK", style: .default, handler: nil)
        alertController.addAction(OKAction)
        self.present(alertController, animated: true, completion: nil)
    }
}
11
Chris Herbst

J'ai peut-être trouvé une meilleure réponse à ce problème, via un article de Krakendev: https://krakendev.io/blog/subclassing-can-suck-and-heres-why .

L'idée est d'utiliser une programmation orientée protocole pour créer une implémentation par défaut d'une alerte uniquement pour UIViewControllers:

protocol Alertable {
    func issueAlert()
}

extension Alertable where Self: UIViewController {
    func issueAlert() {
        // alert code here
    }
}

Maintenant, juste comme ça, chaque UIViewController qui adhère à Alertable aura la méthode issueAlert () à sa disposition sans même avoir à définir sa propre implémentation.

Et, bien sûr, nous pouvons également définir des paramètres pour la fonction issueAlert:

extension Alertable where Self: UIViewController {
    func issueAlert(title: "Default Title", message: String = "Default Message") {
        // alert code here
    }
}

Notre contrôleur de vue peut donc:

issueAlert()

ou

issueAlert(title: "Error", message: "Something went wrong")

Je peux penser à deux avantages de cette approche: vous savez si un contrôleur de vue a accès à cette méthode simplement en regardant le protocole Alertable dans la définition de classe, et les contrôleurs de vue individuels peuvent remplacer cette méthode s'ils souhaitent fournir des fonctionnalités personnalisées . Bien sûr, vous pouvez désormais également spécifier le contrat Alertable comme paramètre de méthode.

4
Ryan Bobrowski

Pourquoi ne pas créer une fonction utilitaire qui renvoie AlertView au ViewController?

self.presentViewController(Utilities.createAlertController("errorMessage"), animated: true, completion: nil);
1
MobileMon

Mis à jour pour Swift 3:

si vous souhaitez afficher le message d'alerte à l'utilisateur utilisé ci-dessous de simples lignes de code;

// définition de fonction:

func showMessageToUser(title: String, msg: String)  {
    let alert = UIAlertController(title: title, message: msg, preferredStyle: UIAlertControllerStyle.alert)
    alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil))
    self.present(alert, animated: true, completion: nil)
}

// appel de fonction:

self.showMessageToUser(title: "Alert", msg: "your message to user")

// Profitez du codage ..!

1
Kiran jadhav