web-dev-qa-db-fra.com

Comment puis-je afficher un message contextuel dans Swift qui disparaît après 3 secondes ou peut être annulé par l'utilisateur immédiatement?

Dans mon application Swift, j'ai un UIViewController avec un seul bouton.

Ce bouton appelle une fonction qui appelle une fenêtre contextuelle qui disparaît après 3 secondes. En outre, après cette heure, il affiche un message sur la console. Le code de cette fonction est le suivant:

func showAlertMsg(title: String, message: String){


    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
    self.presentViewController(alertController, animated: true, completion: nil)
    let delay = 3.0 * Double(NSEC_PER_SEC)
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
    dispatch_after(time, dispatch_get_main_queue(), {
        alertController.dismissViewControllerAnimated(true, completion: nil)
    print("popup disappeared")
    })

}

Cela fonctionne bien, mais je voulais apporter quelques améliorations. Je voulais y ajouter un bouton qui annulera immédiatement cette fenêtre et évitera l'affichage du message dans la console. Existe-t-il un moyen d’afficher ce type de popup à l’utilisateur? Aussi - y a-t-il une manière de montrer dans ce message contextuel le compteur avec le nombre de secondes écoulées qui indique combien de temps il reste avant la disparition de la fenêtre contextuelle?

7
user3766930

Vous pouvez utiliser une variable NSTimer pour décrémenter un compteur, mettre à jour la vue des alertes et la supprimer lorsque le compteur atteint 0. Ce code est adapté de mon Objective-C answer

class ViewController: UIViewController {

    var alertController: UIAlertController?
    var alertTimer: NSTimer?
    var remainingTime = 0
    var baseMessage: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)         
        self.showAlertMsg("Test Alert", message: "This will disappear in ", time: 5)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func showAlertMsg(title: String, message: String, time: Int) {

        guard (self.alertController == nil) else {
            print("Alert already displayed")
            return
        }

        self.baseMessage = message
        self.remainingTime = time

        self.alertController = UIAlertController(title: title, message: self.alertMessage(), preferredStyle: .Alert)

        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
            print("Alert was cancelled")
            self.alertController=nil;
            self.alertTimer?.invalidate()
            self.alertTimer=nil
        }

        self.alertController!.addAction(cancelAction)

        self.alertTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(ViewController.countDown), userInfo: nil, repeats: true)       

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

    func countDown() {

        self.remainingTime -= 1
        if (self.remainingTime < 0) {
            self.alertTimer?.invalidate()
            self.alertTimer = nil
            self.alertController!.dismissViewControllerAnimated(true, completion: {
                self.alertController = nil
            })
        } else {
            self.alertController!.message = self.alertMessage()
        }

    }

    func alertMessage() -> String {
        var message=""
        if let baseMessage=self.baseMessage {
            message=baseMessage+" "
        }
        return(message+"\(self.remainingTime)")
    }     
}
8
Paulw11

Juste au cas où quelqu'un en aurait besoin, il s'agit d'une version Swift 4 de la solution @ Paulw11

import UIKit

class ViewController: UIViewController {

    var alertController: UIAlertController?
    var alertTimer: Timer?
    var remainingTime = 0
    var baseMessage: String?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.showAlertMsg(title: "Test Alert", message: "This will disappear in ", time: 5)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func showAlertMsg(title: String, message: String, time: Int) {

        guard (self.alertController == nil) else {
            print("Alert already displayed")
            return
        }

        self.baseMessage = message
        self.remainingTime = time

        self.alertController = UIAlertController(title: title, message: self.alertMessage(), preferredStyle: .alert)

        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in
            print("Alert was cancelled")
            self.alertController=nil;
            self.alertTimer?.invalidate()
            self.alertTimer=nil
        }

        self.alertController!.addAction(cancelAction)

        self.alertTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(ViewController.countDown), userInfo: nil, repeats: true)

        self.present(self.alertController!, animated: true, completion: nil)
    }

    @objc func countDown() {

        self.remainingTime -= 1
        if (self.remainingTime < 0) {
            self.alertTimer?.invalidate()
            self.alertTimer = nil
            self.alertController!.dismiss(animated: true, completion: {
                self.alertController = nil
            })
        } else {
            self.alertController!.message = self.alertMessage()
        }

    }

    func alertMessage() -> String {
        var message=""
        if let baseMessage=self.baseMessage {
            message=baseMessage+" "
        }
        return(message+"\(self.remainingTime)")
    }
}
1
Dknacht

Je sais que cela ne répond pas directement à votre question, mais avez-vous envisagé d'utiliser MBProgressHUDSCLAlertView ? Ils offrent tous deux des fonctions qui vous permettent d’afficher une alerte qui disparaît après un laps de temps défini. SCLAlertView permet à l'utilisateur d'annuler immédiatement, contrairement à MBProgressHUD. Si vous souhaitez plus d'informations sur la manière de les implémenter, faites-le moi savoir afin que je puisse en ajouter davantage!

0
Dan Levy