我正在使用每秒重复一次的计时器来更新正在播放的内容currentPlaybackTime
,因此我每秒都会根据当前歌曲的进度更新我的标签。我曾经使用NSTimer
或在 Swift aTimer
中每秒重复一次,但是在更改歌曲或开始和停止歌曲时遇到问题,秒标签会滞后(当你听到这首歌时,它会保持 5 秒不变)播放,然后会更新到正确的时间)。然后我继续使用 GCD,我遇到了同样的问题,即使在后台队列中也是如此。然后我去使用 DispatchSourceTimer,我得到了以下日志:
Fired: 2018-03-18 13:22:17 +0000
Timer fired: 2018-03-18 13:22:17 +0000
Fired: 2018-03-18 13:22:18 +0000
Timer fired: 2018-03-18 13:22:18 +0000
Fired: 2018-03-18 13:22:19 +0000
Fired: 2018-03-18 13:22:20 +0000
Timer fired: 2018-03-18 13:22:20 +0000
Fired: 2018-03-18 13:22:21 +0000
Fired: 2018-03-18 13:22:22 +0000
Fired: 2018-03-18 13:22:23 +0000
Fired: 2018-03-18 13:22:24 +0000
Fired: 2018-03-18 13:22:25 +0000
Fired: 2018-03-18 13:22:26 +0000
Fired: 2018-03-18 13:22:27 +0000
Fired: 2018-03-18 13:22:28 +0000
Fired: 2018-03-18 13:22:29 +0000
Fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Timer fired: 2018-03-18 13:22:30 +0000
Fired: 2018-03-18 13:22:31 +0000
Timer fired: 2018-03-18 13:22:31 +0000
Fired: 2018-03-18 13:22:32 +0000
Timer fired: 2018-03-18 13:22:32 +0000
说“Fired”的是实际的偶数处理程序,DispatchSourceTimer
而“Timer Fired”在更新标签等的处理程序函数中。很明显,您可以看到计时器工作正常,但似乎主线程被大量使用。
这是我的代码:
//timer is a DispatchSourceTimer, queue is a concurrent custom queue
public func startTimer() {
timer?.cancel()
timer = DispatchSource.makeTimerSource(queue: queue)
timer?.schedule(deadline: DispatchTime.now(), repeating: .seconds(1))
timer?.setEventHandler { [weak self] in
print("Fired: \(Date())")
DispatchQueue.main.async {
self?.notifyObservers()
}
}
timer?.resume()
}
public func stopTimer() {
timer?.cancel()
timer = nil
}
这里是通知观察者:
private func notifyObservers() {
for observer: TimeObserver in self.timeObservers {
observer.timerFired()
}
}
我维护了一个对象的观察者数组,这些对象希望在定时器触发时得到通知。
我做了一个测试并删除了 for 循环,只是通知了列表中的第一个观察者,它确实加快了速度,但仍然没有解决问题。
如果我只是播放歌曲并且几秒钟后主线程实际上可以处理它并且我可以完美地显示时间,但是当做繁重的事情时,比如使用MPMediaPlayer
框架来改变歌曲或调用时play()
它pause()
开始MPMusicPlayerController
滞后。
任何帮助,将不胜感激。谢谢你。