In my swift app I have a UIViewController with a single button.
This button invokes a function that calls a popup that disappears after 3 seconds. Also, after that time it prints a message to the console. The code of this function is as follows:
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")
})
}
That works fine, but I wanted to introduce some improvement. I wanted to add there a button that will cancel this popup immediately and then avoid displaying the message in the console. Is there a way of displaying such popup to the user? Also - is there a way of showing in this popup message the counter with number of seconds running out that shows how much time is left until the popup disappears?
You can use an NSTimer
to decrement a counter, update the alert view and dismiss the alert view when the counter reaches 0. This code is adapted from my 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)")
}
}
Just in case someone needs it, this is a Swift 4 version of the @Paulw11 solution
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)")
}
}
I know this directly doesn't answer your question, but have you considered using MBProgressHUD SCLAlertView? They both offer functions that allow you to display an alert that disappears after a set amount of time. SCLAlertView allows the user to cancel immediately where as MBProgressHUD does not. If you want more info on how to implement these, let me know so I can add more info!
来源:https://stackoverflow.com/questions/36727474/how-can-i-display-a-popup-message-in-swift-that-disappears-after-3-seconds-or-ca