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

Swift点击按钮启动的计时器无法调用invalidate()停止,求解决方案

解决方案

你的问题核心出在计时器实例的作用域范围错误,以及重复创建计时器实例导致的崩溃,修正方案如下:

问题根源

  • timerCount是onClickAnimate方法内的局部变量,作用域仅在该方法内部,updateCounter方法无法跨方法访问该变量,所以调用invalidate()直接编译报错。
  • 你声明全局变量时出现unrecognized selector错误,是因为重复点击按钮会创建多个计时器实例,旧的实例没有被正确销毁,野实例调用方法触发了崩溃。

正确实现代码

1. 声明类属性

将计时器实例声明为当前ViewController的类属性,不要用局部变量也不要用全局变量,保证当前类的所有方法都可以访问:

// 倒计时数值
var countDown = 5 {
    didSet {
        label.text = String(countDown)
    }
}
// 计时器实例
var timer: Timer?

2. 点击按钮启动计时器

每次启动前先销毁旧的计时器,避免重复创建:

@IBAction func onClickAnimate(_ sender: Any) {
    // 先销毁已有计时器
    timer?.invalidate()
    // 创建新计时器
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateCounter), userInfo: nil, repeats: true)
}

3. 计时回调逻辑

倒计时归0后直接访问类属性的计时器实例销毁即可:

@objc func updateCounter(){
    if countDown > 0 {
        countDown -= 1
    }
    if countDown == 0 {
        countDown = 5
        timer?.invalidate()
        // 销毁后置空,避免野指针
        timer = nil
    }
}

注意事项

  • 禁止重复创建计时器实例,每次启动前必须先调用旧实例的invalidate()方法
  • 计时器销毁后建议手动置空属性,避免后续误调用野实例
  • 不需要将计时器声明为全局变量,放在当前使用类的属性中即可,避免全局污染和多页面调用冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:15:03