Dismiss UIAlertView after 5 Seconds Swift
Asked Answered
B

11

40

I've created a UIAlertView that contains a UIActivityIndicator. Everything works great, but I'd also like the UIAlertView to disappear after 5 seconds.

How can I Dismiss my UIAlertView after 5 seconds?

 var alert: UIAlertView = UIAlertView(title: "Loading", message: "Please wait...", delegate: nil, cancelButtonTitle: "Cancel");

 var loadingIndicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRectMake(50, 10, 37, 37)) as UIActivityIndicatorView
 loadingIndicator.center = self.view.center;
 loadingIndicator.hidesWhenStopped = true
 loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
 loadingIndicator.startAnimating();

 alert.setValue(loadingIndicator, forKey: "accessoryView")
 loadingIndicator.startAnimating()

 alert.show()
Bluet answered 23/12, 2014 at 4:5 Comment(1)
If you are loading something, why would you want to hide the alert after a fixed time? Wouldn't you rather hide it when the loading is complete?Renunciation
W
48

You can dismiss your UIAlertView after a 5 second delay programmatically, like so:

alert.show()

// Delay the dismissal by 5 seconds
let delay = 5.0 * Double(NSEC_PER_SEC)
var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
    alert.dismissWithClickedButtonIndex(-1, animated: true)
})
Wheatear answered 23/12, 2014 at 4:17 Comment(3)
There is no need to create the 2nd function. Inside the dispatch_after block simply call alert.dismissWithClickedButtonIndex(-1, animated: true)Peccadillo
BTW - I like this approach better than using a timer.Peccadillo
@Peccadillo It's more flexible, but more ugly. I can see why people would avoid it for aesthetic reasons alone.Wheatear
C
101

A solution to dismiss an alert automatically in Swift 3 and Swift 4 (Inspired by part of these answers: [1], [2], [3]):

// the alert view
let alert = UIAlertController(title: "", message: "alert disappears after 5 seconds", preferredStyle: .alert)
self.present(alert, animated: true, completion: nil)

// change to desired number of seconds (in this case 5 seconds)
let when = DispatchTime.now() + 5
DispatchQueue.main.asyncAfter(deadline: when){
  // your code with delay
  alert.dismiss(animated: true, completion: nil)
}

Result:

enter image description here

Cheju answered 8/10, 2016 at 9:37 Comment(0)
W
48

You can dismiss your UIAlertView after a 5 second delay programmatically, like so:

alert.show()

// Delay the dismissal by 5 seconds
let delay = 5.0 * Double(NSEC_PER_SEC)
var time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
    alert.dismissWithClickedButtonIndex(-1, animated: true)
})
Wheatear answered 23/12, 2014 at 4:17 Comment(3)
There is no need to create the 2nd function. Inside the dispatch_after block simply call alert.dismissWithClickedButtonIndex(-1, animated: true)Peccadillo
BTW - I like this approach better than using a timer.Peccadillo
@Peccadillo It's more flexible, but more ugly. I can see why people would avoid it for aesthetic reasons alone.Wheatear
K
14

For swift 4 you can use this code

let alertController = UIAlertController(title:"Alert",message:nil,preferredStyle:.alert)
self.present(alertController,animated:true,completion:{Timer.scheduledTimer(withTimeInterval: 5, repeats:false, block: {_ in
    self.dismiss(animated: true, completion: nil)
})})
Kalpa answered 2/3, 2018 at 5:40 Comment(0)
R
13

in swift 2 you can do this. Credit to @Lyndsey Scott

 let alertController = UIAlertController(title: "youTitle", message: "YourMessage", preferredStyle: .Alert)
                self.presentViewController(alertController, animated: true, completion: nil)
                let delay = 5.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)
                })
Rotterdam answered 2/9, 2015 at 11:57 Comment(3)
What happen is there is an ok button on the alert and that the user clicks it before the dispatch is executed ?Comment
I was wondering if it would crash since the alertControler would already dismissed if the user presed the ok button before the 5 seconds delay. I tryed it and I do not get any error message. So I guess it is ok.Comment
On Android I made an auto-closing message box that updates the ok button caption with a countdown OK (5), OK(4), ....OK(1). I would very much like to do something similar but I don't think I can with an alertController.Comment
A
6

Create the alert object as a global variable. You can use a NSTimer for this purpose.

var timer = NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: Selector("dismissAlert"), userInfo: nil, repeats: false)


func dismissAlert()
{
    // Dismiss the alert from here
    alertView.dismissWithClickedButtonIndex(0, animated: true)

}

NOTE:

Important: UIAlertView is deprecated in iOS 8. (Note that UIAlertViewDelegate is also deprecated.) To create and manage alerts in iOS 8 and later, instead use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert.

Reference : UIAlertView

Action answered 23/12, 2014 at 4:18 Comment(0)
P
1

For Swift 3

let alert = UIAlertController(title: “Alert”, message: “Message”,preferredStyle: UIAlertControllerStyle.alert)
self.present(alert, animated: true, completion: nil)
 DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double((Int64)(5.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {() -> Void in
     alert.dismiss(animated: true, completion: {() -> Void in
 })
})
Prejudice answered 5/9, 2017 at 13:23 Comment(0)
F
1

@ronatory 's answer in c#

var when = new DispatchTime(DispatchTime.Now, 
TimeSpan.FromSeconds(5));
DispatchQueue.MainQueue.DispatchAfter(when, () =>
{
    // your code with delay
    alertController.DismissModalViewController(true);
});
Flattie answered 20/2, 2019 at 19:52 Comment(0)
G
1

In iOS 8.0+ UIAlertController inherits from UIViewController, so, it is just that, a view controller. So, all the restrictions apply. That's why when there's a possibility that the view gets dismissed by the user, it's not entirely safe to try to dismiss it without proper checks.

In the following snippet there's an example of how this can be achieved.

func showAutoDismissableAlert(
      title: String?,
      message: String?,
      actions: [MyActionWithPayload], //This is just an struct holding the style, name and the action in case of the user selects that option
      timeout: DispatchTimeInterval?) {

  let alertView = UIAlertController(
      title: title,
      message: message,
      preferredStyle: .alert
  )

  //map and assign your actions from MyActionWithPayload to alert UIAlertAction
  //(..)

  //Present your alert
  //(Here I'm counting on having the following variables passed as arguments, for a safer way to do this, see https://github.com/agilityvision/FFGlobalAlertController) 
  alertView.present(viewController, animated: animated, completion: completion)


  //If a timeout was set, prepare your code to dismiss the alert if it was not dismissed yet
  if let timeout = timeout {
    DispatchQueue.main.asyncAfter(
       deadline: DispatchTime.now() + timeout,
       execute: { [weak alertView] in
            if let alertView = alertView, !alertView.isBeingDismissed {
                alertView.dismiss(animated: true, completion: nil)
            }
        }
    }
}
Gauzy answered 13/8, 2019 at 7:43 Comment(0)
C
0

//Generic Function For Dismissing alert w.r.t Timer

/** showWithTimer */
public func showWithTimer(message : String?, viewController : UIViewController?) {

    let version : NSString = UIDevice.current.systemVersion as NSString
    if  version.doubleValue >= 8 {
        alert = UIAlertController(title: "", message: message, preferredStyle:.alert)
        viewController?.present(alert ?? UIAlertController(), animated:true, completion:nil)
        let when = DispatchTime.now() + 5
        DispatchQueue.main.asyncAfter(deadline: when){
            self.alert?.dismiss(animated: true, completion: nil)
        }
    }
}
Comstockery answered 28/2, 2018 at 13:13 Comment(0)
W
0

You can make it as an extension to reuse the disappearing alert in multiple view controllers.

extension UIViewController {
func disappearingAlert(title: String, message: String){
    // the alert view
    let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
    self.present(alert, animated: true, completion: nil)

    // change to desired number of seconds (in this case 5 seconds)
    let when = DispatchTime.now() + 5
    DispatchQueue.main.asyncAfter(deadline: when){
      // your code with delay
      alert.dismiss(animated: true, completion: nil)
    }
}

}

Witter answered 18/10, 2022 at 7:53 Comment(0)
F
-1

I'm not an expert but this works for me and I guess is easier

let alert = UIAlertController(title: "", message: "YOUR MESSAGE", preferredStyle: .alert)
present(alert, animated: true) {
   sleep(5)
   alert.dismiss(animated: true)
}
Flashbulb answered 14/11, 2018 at 1:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.