Swift中UIAlertController按钮倒计时点击Cancel崩溃问题求助
解决Swift弹窗点击Cancel按钮崩溃的问题
嗨,我来帮你搞定这个崩溃问题!
崩溃原因分析
当你点击Cancel按钮时,UIAlertController会被立即dismiss,此时presentedViewController已经变成nil了,但你的代码里用了as!强制解包这个可选值,这就直接触发了“Unexpectedly found nil while unwrapping an Optional value”错误。另外,就算弹窗被关掉了,你的timer还在继续运行,每次触发都会尝试获取已经不存在的弹窗,这也会持续引发问题。
修复方案
我给你调整了代码,主要做了这几个关键修改:
- 用可选绑定(
if let/guard let)替代强制解包,安全获取弹窗实例 - 在Cancel按钮的handler里停止timer,并重置计数
- 把timer和timerCount的定义移到ViewController类内部,避免全局变量的潜在问题
- 添加
[weak self]避免循环引用,防止内存泄漏
修正后的完整代码
class ViewController: UIViewController { // 把变量移到类内部,更符合Swift规范,同时设为可选类型更安全 private var timer: Timer? private var timerCount: Int = 5 override func viewDidLoad() { super.viewDidLoad() } @IBAction func okButton(_ sender: Any) { showAlertView() } func showAlertView() { // 每次弹窗前重置计数,避免上次的残留值影响 timerCount = 5 let alertController = UIAlertController(title: "Title", message: "Message of alert", preferredStyle: .alert) let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil) okAction.isEnabled = false alertController.addAction(okAction) // 给Cancel按钮添加handler,弹窗消失时立即停止timer let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { [weak self] _ in self?.timer?.invalidate() self?.timer = nil } alertController.addAction(cancelAction) present(alertController, animated: true) { [weak self] in // 启动倒计时timer self?.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self!, selector: #selector(self!.countDownTimer), userInfo: nil, repeats: true) } } @objc func countDownTimer() { timerCount -= 1 // 用guard let安全获取弹窗和按钮,避免nil解包崩溃 guard let alertController = presentedViewController as? UIAlertController, let okAction = alertController.actions.first else { // 如果弹窗已经不存在,立即停止timer timer?.invalidate() timer = nil return } if timerCount == 0 { timer?.invalidate() timer = nil okAction.setValue("Ok", forKey: "title") okAction.isEnabled = true } else { okAction.setValue("Ok \(timerCount)", forKey: "title") } } }
额外说明
- 把
timer改为可选类型后,我们可以更清晰地管理timer的启停状态 - 在
countDownTimer方法里增加了兜底判断,就算timer在弹窗消失后意外触发,也能立即停止并返回,不会引发崩溃 - 每次弹窗前重置
timerCount,确保每次弹窗的倒计时都是从5开始
内容的提问来源于stack exchange,提问作者Dave B.
相关产品推荐
相关产品推荐

