ios - 为 AVPlayer 更新时 UISlider 跳转
问题描述
我尝试使用 UISlider 实现简单的播放器,以指示当前音频文件的时间。
在代码中,我添加了两个观察者:
slider.rx.value.subscribe(onNext: { value in
let totalTime = Float(CMTimeGetSeconds(self.player.currentItem!.duration))
let seconds = value * totalTime
let time = CMTime(seconds: Double(seconds), preferredTimescale: CMTimeScale(NSEC_PER_SEC))
self.player.seek(to: time)
}).disposed(by: bag)
let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
player.addPeriodicTimeObserver(forInterval: interval, queue: nil) { [weak self] time in
self?.updateSlider(with: time)
}
具有一个私有功能:
private func updateSlider(with time: CMTime) {
let currentTime = CMTimeGetSeconds(time)
var totalTime = CMTimeGetSeconds(player.currentItem!.duration)
if totalTime.isNaN {
totalTime = 0
}
startLabel.text = Int(currentTime).descriptiveDuration
endLabel.text = Int(totalTime).descriptiveDuration
slider.value = Float(currentTime / totalTime)
}
播放音频时,一切都很好,滑块也更新了很多。当我在播放音频时尝试手动移动滑块时会出现问题,然后它会跳转。为什么?
更新:
我知道为什么。因为我更新了两次:手动和玩家观察者,但是如何防止这种行为?我不知道;)请帮忙。
解决方案
解决此问题的一种简单方法是防止在触摸滑块时addPeriodicTimeObserver
调用。self?.updateSlider(with: time)
这可以通过UISlider
sisTracking
属性确定:
是跟踪
一个布尔值,指示控件当前是否正在跟踪触摸事件。
在跟踪触摸事件的过程中,控件将此属性的值设置为 true。当跟踪结束或因任何原因被取消时,它会将此属性设置为 false。
参考:https ://developer.apple.com/documentation/uikit/uicontrol/1618210-istracking
这存在于UIControl
您可以通过这种方式使用的所有元素中:
player.addPeriodicTimeObserver(forInterval: interval, queue: nil) { [weak self] time in
//check if slider is being touched/tracked
guard self?.slider.isTracking == false else { return }
//if slider is not being touched, then update the slider from here
self?.updateSlider(with: time)
}
通用示例:
@IBOutlet var slider: UISlider!
//...
func startSlider() {
slider.value = 0
slider.maximumValue = 10
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] (timer) in
print("Slider at: \(self?.slider.value)")
guard self?.slider.isTracking == false else { return }
self?.updateSlider(to: self!.slider.value + 0.1)
}
}
private func updateSlider(to value: Float) {
slider.value = value
}
我敢肯定还有其他(更好的)方法,但我在 RxSwift 中做得不多(还)。
我希望这已经足够好了。
推荐阅读
- java - Spring Boot批处理MultiResourceItemReader:如何使用@Value()从jar位置读取文件
- google-api - 检索每个地点的多张图片
- python - 将整数列表转换为位列表 Python
- python-3.x - 如何将存储在 Google Drive 中的本地模块导入 Google Collab?
- python - 是否可以从部分 URL 将文件上传到 S3?文件.aa、文件.ab、文件.ac
- node.js - 谷歌云 CPU 分析未显示有用数据
- asp.net-core - 如何在不需要电子邮件确认的情况下更改 ASP.NET Identity 用户的电子邮件?
- javascript - 如何在 Strapi v3 中制作多级(嵌套)类别?
- python - Pandas:过滤以获取包含不在指定列表中的字符的行
- r - 将 R 中的 lm 函数与 foreach 一起用于列表中的每个值