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

Swift中点击TextField后计时器停止的原因及解决咨询

TableViewHeader计时器点击TextField停止的问题解决

问题原因

根本原因是RunLoop模式切换:默认通过Timer.scheduledTimer创建的计时器,会被添加到RunLoop的DefaultRunLoopMode下。当点击TextField使其成为第一响应者时,系统会将RunLoop切换到UITrackingRunLoopMode(专门处理触摸交互、滚动等操作),此时DefaultRunLoopMode下的计时器会暂停触发,表现为计时器“停止”。

不需要单独线程管理计时器,因为UI操作必须在主线程执行,计时器本身也应该在主线程运行,单独线程反而会引发UI更新的线程安全问题。

解决方案

修改WorkoutTimerManager的核心逻辑,确保计时器在RunLoop的通用模式下运行,同时修正计时起点的问题:

class WorkoutTimerManager {
    static let shared = WorkoutTimerManager()
    private var sec = 0
    private var min = 0
    private var timer: Timer? // 改为可选类型,避免初始空Timer的无效问题
    private var date: Date?
    
    var timerLbl: UILabel?
    
    private init() {}
    
    func startTimer() {
        stopTimer() // 先停止已有计时器,避免重复启动
        date = Date() // 重置计时起始时间
        timer = Timer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
        // 将计时器添加到RunLoop的commonModes,确保交互时也能触发
        if let timer = timer {
            RunLoop.current.add(timer, forMode: .commonModes)
        }
    }
    
    func stopTimer() {
        timer?.invalidate()
        timer = nil
    }
    
    @objc private func updateTimer() {
        guard let date = date, let timerLbl = timerLbl else { return }
        
        let elapsedSec = abs(Int(date.timeIntervalSinceNow))
        sec = elapsedSec % 60
        min = elapsedSec / 60
        
        // 明确在主线程更新UI,保障安全性
        DispatchQueue.main.async {
            timerLbl.text = String(format: "%02d:%02d", self.min, self.sec)
        }
    }
}

额外优化建议

  • 避免在tableView(_:viewForHeaderInSection:)中重复启动计时器:TableView的HeaderView可能会因滚动被复用,每次创建Header都调用startTimer()会导致计时器多次启动。建议在ViewController的viewDidLoad或业务逻辑触发时启动计时器,而非Header创建时。
  • 管理HeaderView的引用:当HeaderView被销毁时,清空WorkoutTimerManager.shared.timerLbl的引用,避免野指针和不必要的UI更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:21:39