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

Timer设置重复触发却仅调用一次selector的问题求助

问题解决:Timer重复触发仅调用一次Selector的修复方案

你已经通过修复Timer的fireDate相关问题解决了Timer仅触发一次的问题,这里整理了完整的修正后代码和关键细节,供你和其他开发者参考:

核心代码实现

1. 录制按钮初始化

let photoButton: UIButton = {
    let but = UIButton(type: .custom)
    but.layer.cornerRadius = 40
    but.layer.borderColor = UIColor.white.cgColor
    but.layer.borderWidth = 4
    but.clipsToBounds = true
    but.addTarget(self, action: #selector(takeVideo), for: .touchDown)
    but.addTarget(self, action: #selector(stopVideo), for: [.touchUpInside, .touchUpOutside])
    but.translatesAutoresizingMaskIntoConstraints = false
    return but
}()

2. 长按开始录制与Timer初始化

@objc func takeVideo() {
    progressBar.isHidden = false
    timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateProgressbar), userInfo: nil, repeats: true)
    startTime = Date().timeIntervalSince1970
    timer?.fire() // 立即触发第一次进度更新,避免延迟
}

3. 停止录制与Timer终止

@objc func stopVideo() {
    timer?.invalidate()
    // 这里添加停止视频录制的逻辑
}

4. 进度条更新逻辑

@objc private func updateProgressbar() {
    let maxLength = 7.0
    guard let startTime = startTime else { return }
    let difference = Date().timeIntervalSince1970 - startTime
    progressBar.progress = Float(difference / maxLength)
    
    if difference >= maxLength {
        stopVideo() // 达到7秒自动停止录制并终止Timer
    }
}

5. 视图控制器异步呈现

let recorder = RecorderViewController()
recorder.db = db
DispatchQueue.main.async {
    self.present(recorder, animated: true)
}

关键修复要点

  • Timer触发逻辑修正:确保使用Timer.scheduledTimer并设置repeats: true,同时调用timer?.fire()让Timer立即执行一次,避免进度条出现初始延迟。
  • 安全的时间差计算:添加guard let解包startTime,避免可选值为空导致的崩溃。
  • 主线程UI操作:视图控制器的呈现放在主队列异步执行,保证所有UI操作都在主线程完成,避免线程冲突问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:29:58