5秒后关闭Swift中的UIAlertView。

40

我已创建了一个包含UIActivityIndicator的UIAlertView。一切都很顺利,但我还希望UIAlertView在5秒后消失。

我该如何在5秒后解散我的UIAlertView?

 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()

如果你正在加载某些内容,为什么要在固定时间后隐藏警告框呢?难道不应该在加载完成后再隐藏它吗? - drewag
11个回答

101

Swift 3Swift 4 中自动解除警报的解决方案(灵感来自这些答案的一部分:[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)
}

结果:

输入图像描述


48

你可以通过编程的方式在5秒后自动关闭UIAlertView,代码如下:

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)
})

不需要创建第二个函数。在 dispatch_after 块内,只需调用 alert.dismissWithClickedButtonIndex(-1, animated: true) 即可。 - rmaddy
顺便说一句 - 我更喜欢这种方法,而不是使用计时器。 - rmaddy
1
@rmaddy 它更加灵活,但是更加丑陋。我可以理解为什么人们会因为审美原因而避免使用它。 - Lyndsey Scott

14

对于 Swift 4,您可以使用以下代码

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)
})})

13

在Swift 2中,你可以这样做。感谢@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)
                })

如果在警告框上有一个“确定”按钮,并且用户在执行调度之前单击了它,会发生什么? - Regis St-Gelais
我在想如果用户在5秒延迟之前按下ok按钮,alertControler已经被解除了,那么它是否会崩溃。我尝试了一下,没有收到任何错误消息。所以我想这应该没问题。 - Regis St-Gelais
在Android上,我制作了一个自动关闭的消息框,它会更新“确定”按钮的标题,并显示倒计时OK(5),OK(4)......OK(1)。我非常希望能够做类似的事情,但我不认为我可以使用alertController实现。 - Regis St-Gelais

6
将警报对象创建为全局变量。 您可以使用NSTimer来实现这一目的。
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)

}

注意:

重要提示:UIAlertView在iOS 8中已经弃用。(请注意,UIAlertViewDelegate也已弃用。)为了在iOS 8及以后的版本中创建和管理警告框,请改用preferredStyle为UIAlertControllerStyleAlert的UIAlertController。

参考文献:UIAlertView


1
对于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
 })
})

1
@ronatory在C#中的答案
var when = new DispatchTime(DispatchTime.Now, 
TimeSpan.FromSeconds(5));
DispatchQueue.MainQueue.DispatchAfter(when, () =>
{
    // your code with delay
    alertController.DismissModalViewController(true);
});

1
在iOS 8.0及以上版本中,UIAlertController继承自UIViewController,因此它只是一个视图控制器。因此,所有限制都适用。这就是为什么当用户可能会关闭视图时,没有进行适当的检查就试图关闭视图是不完全安全的原因。
以下代码片段展示了如何实现这一点。
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)
            }
        }
    }
}

0

//定时器相关的警报消除通用函数

/** 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)
        }
    }
}

0

你可以将其作为扩展来重复使用在多个视图控制器中消失的警报。

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)
    }
}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接