###前提・実現したいこと
再生中の音楽のデータを画面に表示するのみのアプリを作っています。
そこで、timer
とcurrentPlaybackTime
を使って再生時間を表示するUILabelを作ったのですが、体感で0.5秒くらい実際の再生時間と表示している時間がずれているのです。表示の方が0.5秒遅いのです。
以下が実際のコードです。
swift
1 override func viewDidLoad() { 2 //一部省略 3 timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true) 4 } 5 6 func updateTime() { 7 if player.nowPlayingItem != nil { 8 count = Int(player.currentPlaybackTime) 9 let min = count / 60 10 let sec = count % 60 11 timeLabel.text = String(format: "%02d:%02d", min, sec)
###考察
どうやら、一度player.currentPlaybackTime
をInt型にするとズレるようです。
そのため、以下のように
swift
1 func updateTime() { 2 if player.nowPlayingItem != nil { 3 timeLabel.text = String(player.currentPlaybackTime)
とすると完全に同期して表示されるようです。
ですが、実際に表示させたいものはmm:ssという形であり、
秒数ssを取得するのに、%
演算子を使いたいため、
一度TimeInterval型からInt型にする必要があると考えています。
###試したこと
timer
のtimeInterval
引数を0.1
や0.01
としても変わりませんでした。
実際の処理でタイムラグが発生しているように思えます。
###追記
2017.8.20
再生時間と同期しているか、というチェックの方法はアプリの画面を起動し、上にコントロールセンターのオーディオコントロールの画面を表示してチェックしています。
そのため、iOSのシステム的には小数点以下を切り捨てにして表示していると思うので、
Int(player.currentPlaybackTime)
として切り捨てても問題ないのでは、と考えました。
また、剰余計算にtruncatingRemainder(dividingBy: 60)
やsec - (sec / 60) * 60
を使っても、mm:ss
のString型にする方法がわからず・・・
無理に代入すると01:14532...
という形になってしまいました・・・
現時点では一度count
にplayer.currentPlaybackTime
代入せず、直接Int()
内に入れることでタイムラグがほぼ解消しました。
swift
1 if player.nowPlayingItem != nil { 2 let min = Int(player.currentPlaybackTime) / 60 3 let sec = Int(player.currentPlaybackTime.truncatingRemainder(dividingBy: 60)) 4 //let sec = Int(player.currentPlaybackTime) % 60よりもなぜかラグが少ないです。 5 timeLabel.text = String(format: "%02d:%02d", min, sec) 6 }
ですが、あくまでも タイムラグが少なくなった ということで根本の解決にはなっていない気がします・・・
timerを0.001秒にし、上記コードにしても、
ごくわずかなズレは残り、また、他のアプリなどを起動し、端末に負担がかかっているときはよりズレて表示されているような気がします・・・
どうかもう一度、お力添えをお願いいたします・・・
###再考察
String(format:)
の形にも慣れていないので、そこでも問題があるのだろうか、とも考えています。
swift
1timeLabel.text = String(format: "%02d:%02d", Int(min), Int(sec))
としても、ラグはあったのですが・・・。
###補足情報(言語/FW/ツール等のバージョンなど)
swift3 xcode8