現在再生中の を更新するために毎秒繰り返すタイマーを使用しているcurrentPlaybackTime
ため、現在の曲の進行状況で毎秒ラベルを更新しています。NSTimer
以前は Swift で orを使用してTimer
1 秒ごとに繰り返していましたが、曲を変更したり、曲を開始および停止したりするときに問題が発生しました。再生してから、正しい時間に更新されます)。その後、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
が始まります。
どんな助けでも大歓迎です。ありがとうございました。