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

SwiftUI中AVPlayer添加时间观察者导致滑动卡顿问题求助

SwiftUI音乐播放器滑块卡顿问题解决

问题原因

你的代码中,AVPlayer的时间观察者直接在主队列每秒更新@Published var progress,这会触发SwiftUI视图的频繁重绘。当用户滑动滑块时,主队列需要同时处理触摸交互事件和观察者的UI更新任务,导致主线程阻塞,出现滑动卡顿。

解决方案

1. 将时间观察者回调移到后台队列

把观察者的执行队列从主队列改为后台队列,仅在需要更新UI时回到主队列,减少主线程压力:

func currentTimeAddObserver() {
    self.timeObserver = self.player.addPeriodicTimeObserver(
        forInterval: CMTimeMakeWithSeconds(1, preferredTimescale: 1),
        queue: DispatchQueue.global(qos: .utility) // 使用后台队列执行回调
    ) { [weak self] time in
        guard let self = self else { return }
        guard !self.isSeekingToTime else { return }
        
        // 仅在非滑动时,回到主队列更新进度
        DispatchQueue.main.async {
            self.progress = CMTimeGetSeconds(time)
        }
    }
}

2. 确保滑动状态判断的及时性

在SwiftUI的Slider组件中,通过onEditingChanged实时更新isSeekingToTime,确保滑动过程中观察者完全停止更新progress,避免和用户操作冲突:

Slider(
    value: $musicPlayer.progress,
    in: 0...musicPlayer.totalDuration,
    onEditingChanged: { isEditing in
        musicPlayer.isSeekingToTime = isEditing
        // 滑动结束后再同步播放器进度
        if !isEditing {
            let targetTime = CMTimeMakeWithSeconds(musicPlayer.progress, preferredTimescale: 1)
            musicPlayer.player.seek(to: targetTime)
        }
    }
)

3. 补充观察者的正确移除逻辑

确保在播放器销毁时移除时间观察者,避免内存泄漏(虽然不直接解决卡顿,但属于必要优化):

func removeObserver() {
    if let observer = timeObserver {
        player.removeTimeObserver(observer)
        timeObserver = nil
    }
}

deinit {
    removeObserver()
}

额外优化

AVPlayer的volume属性范围是0.0~1.0,设置为2.0不会有额外效果,建议改为_player.volume = 1.0,避免无效配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:57:19