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
相关产品推荐
相关产品推荐

