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

Swift:调用invalidate后计时器未停止反而加速?

问题分析与解决方案

嘿,我一眼就揪出你这个秒表加速问题的根源啦!

问题原因

你每次点击「Start Timer」按钮时,都会创建一个全新的Timer实例,但之前已经在运行的Timer并没有被正确终止。举个具体场景:

  • 第一次点Start,创建了Timer A,它会每秒调用updateTimer让counter加0.1;
  • 要是不小心快速点了两次Start(哪怕按钮刚要被禁用前),Timer变量会被覆盖成新的Timer B,而Timer A还在后台偷偷运行;
  • 这时候两个Timer会同时触发updateTimer,counter每秒就会加0.2,看起来就是「加速」了;
  • 点击Start的次数越多,同时运行的Timer就越多,秒表速度自然越来越快。

而且你的pauseButton里虽然调用了timer.invalidate(),但这个方法只能终止最后一次创建的Timer,之前多出来的Timer依然在后台跑,根本没被管控到。

修复方案

只需要在创建新Timer前,先确保旧的Timer已经被停止并清理掉,同时完善Timer的管理逻辑:

1. 修改playButton方法,创建新Timer前先终止旧Timer

@objc func playButton(_ sender : Any) {
    // 先停止已有计时器,避免多个实例同时运行
    if timer != nil {
        timer.invalidate()
        timer = nil
    }
    
    timer = Timer.scheduledTimer(timeInterval: 1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)
    startButton.isEnabled = false
    stopButton.isEnabled = true
    isRunning = true
    self.view.addSubview(stopButton)
    startButton.isHidden = true
    stopButton.isHidden = false
}

2. 完善pauseButton方法,终止Timer后置空变量

@objc func pauseButton(_ sender: Any) {
    self.view.addSubview(startButton)
    timer.invalidate()
    timer = nil // 置空避免野指针,也能帮助后续判断Timer状态
    stopButton.isHidden = true
    startButton.isHidden = false
    startButton.isEnabled = true
    stopButton.isEnabled = false
    isRunning = false
}

额外小建议

你的Timer时间间隔设的是1秒,但updateTimer里每次给counter加0.1,这逻辑有点矛盾(秒表每秒只跳0.1?)。如果是想做0.1秒精度的秒表,应该把Timer的timeInterval改成0.1,这样逻辑更合理:

timer = Timer.scheduledTimer(timeInterval: 0.1, target: self , selector: #selector(updateTimer), userInfo: nil, repeats: true)

总结

核心问题就是重复创建Timer却未清理旧实例,导致多个Timer同时触发更新方法。只要在创建新Timer前确保旧Timer已经被停止并置空,就能彻底解决秒表加速的问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:50:18