iOS Swift:如何避免Timer调用invalidate()时触发fire()?
问题分析与解决
你的文档理解没有错
Apple文档关于invalidate()的描述是准确的:调用该方法后,Timer会停止所有后续的自动触发请求,并从RunLoop中移除,不会再被RunLoop调度自动执行。你看到的额外触发并不是invalidate()导致的,而是代码里的手动调用逻辑。
问题根源
看你的startMyTimer()函数:
private func startMyTimer() { myTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in print("my timer: Fired \(Date.now.mediumTimeLocalizedDescription)") } myTimer!.fire() // 这里是关键! }
每次创建新的Timer后,你都手动调用了fire(),强制Timer立刻执行一次回调。在你3秒后的重启逻辑里:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) { self.myTimer!.fire() print("my timer: invalidating \(Date.now.mediumTimeLocalizedDescription)") self.myTimer!.invalidate() self.myTimer = nil self.startMyTimer() // 这里调用startMyTimer,又会手动触发一次fire }
调用startMyTimer()时,新创建的Timer会立刻执行fire(),这就是你看到my timer: Fired 14:27:17这条额外输出的原因。
解决办法
根据你的预期输出,你希望重启后的Timer从10秒后才开始触发,所以只需要去掉startMyTimer()里的手动fire()调用即可:
private func startMyTimer() { myTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in print("my timer: Fired \(Date.now.mediumTimeLocalizedDescription)") } // 移除这一行:myTimer!.fire() }
如果首次启动时需要立刻触发,重启时不需要,可以加个参数区分:
private func startMyTimer(shouldFireImmediately: Bool = true) { myTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { timer in print("my timer: Fired \(Date.now.mediumTimeLocalizedDescription)") } if shouldFireImmediately { myTimer!.fire() } } // 首次启动 startMyTimer() // 重启时不立刻触发 self.startMyTimer(shouldFireImmediately: false)
内容的提问来源于stack exchange,提问作者user14806416
相关产品推荐
相关产品推荐

