You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift:ViewController手动Dismiss时停止Timer的实现问询

解决Swift中手动dismiss后Timer仍运行的问题

嘿,这个坑我之前踩过!问题出在你现在的Timer是局部变量,而且没有在ViewController被手动dismiss时主动停止它——RunLoop会一直持有这个Timer,直到它完成循环,所以哪怕VC已经被销毁,计时归零的逻辑还是会触发。下面给你修改方案:

第一步:把Timer改成ViewController的实例变量

首先在你的ViewController类里声明一个可选类型的Timer变量,这样我们能在其他方法里访问并控制它:

class YourViewController: UIViewController {
    var countdownTimer: Timer? // 新增实例变量
    var counter = 10 // 假设你的初始计数是10,根据实际情况调整
    @IBOutlet weak var timerLabel: UILabel!
    
    // 其他代码...
}

第二步:初始化Timer并赋值给实例变量

在viewDidLoad里,把原来的局部Timer替换成赋值给实例变量的写法:

override func viewDidLoad() {
    super.viewDidLoad()
    // 初始化Timer并保存引用
    countdownTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
    timerLabel.text = "\(counter)"
}

第三步:手动dismiss时停止Timer

有两种方式确保手动dismiss时Timer停止:

方式一:在手动调用dismiss的地方主动停止

如果你是通过按钮或其他事件手动触发dismiss,在调用dismiss前先停止Timer:

@IBAction func manualDismissButtonTapped(_ sender: UIButton) {
    countdownTimer?.invalidate()
    countdownTimer = nil // 置空避免无效引用
    dismiss(animated: true, completion: nil)
}

方式二:利用ViewController生命周期方法自动处理

如果不确定手动dismiss的触发点,或者想统一处理所有dismiss场景,可以重写viewWillDisappear方法,判断VC是否正在被dismiss,然后停止Timer:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // 只有当VC被dismiss时才停止Timer(避免push到其他VC时误停)
    if isBeingDismissed {
        countdownTimer?.invalidate()
        countdownTimer = nil
    }
}

第四步:完善自动dismiss的逻辑

在计时归零自动dismiss的时候,也要记得停止Timer,避免重复触发:

@objc func updateCounter() {
    if counter >= 0 {
        timerLabel.text = "\(counter)"
        counter -= 1
    }
    if counter == -1 { // 这里注意:因为counter在显示后减1,所以当显示0后,counter会变成-1,此时触发dismiss更准确
        print("COUNTER GOT TO ZERO")
        countdownTimer?.invalidate()
        countdownTimer = nil
        dismiss(animated: true, completion: nil)
    }
}

小提示:原来的逻辑里,当counter等于0时显示0,然后减1变成-1,但此时会触发dismiss。如果按原来的判断counter == 0,会在显示0的同时触发dismiss,可能导致UI显示和dismiss不同步,改成判断counter == -1会更合理——等显示完0之后再执行dismiss。

内容的提问来源于stack exchange,提问作者King

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:51:30