isPlayingがおかしくなる問題に対応
動作を確認した環境
環境 | 情報 |
---|---|
Xcode | 6.3.2 (6D2105) |
iOS | 8.3 |
Swift | 1.2 |
Date | 2015/6/7 |
isPlayingがおかしくなる問題に対応
問題の詳しい内容はこちらを参照。
MPMusicPlayerController::playbackStateがおかしくなる問題 - 開発メモ
http://seeku.hateblo.jp/entry/2014/07/07/164821
簡単に言うと、MPMusicPlayerController::playbackStateは信頼出来ないということ。では、どうするべきか?
class SK4MusicPlayerAdmin: NSObject { ※関係ない部分は省略 /// 再生中か? func isPlaying() -> Bool { // player.playbackStateは信頼出来ないので、 // AVAudioSessionで再生状況を調べる let av = AVAudioSession.sharedInstance() return av.otherAudioPlaying } }
こんな感じにしてみた。つまり、player.playbackStateはバッサリあきらめて、AVAudioSessionのレベルでオーディオが再生されているかどうかをチェックするようにしてみた。
ただし、この形に修正すると、今度はMPMusicPlayerControllerPlaybackStateDidChangeNotificationで問題が起きる。
通知が来た時点で、AVAudioSessionのレベルに変更が反映されてないという・・・ さり気なく、これも、Appleの実装ミスのような気がしないでもないんだけど。
仕方がないので通知を受けた時点で、その後の更新処理を遅らせて実行するように修正。
class SK4MusicPlayerAdmin: NSObject { func playbackStateChanged(notify: NSNotification) { // 通知の直後はAVAudioSessionで再生状況が取れないので、 // 少し遅らせてチェックする let time = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_SEC / 10)) let queue = dispatch_get_main_queue() dispatch_after(time, queue) { [weak self] in self?.onPlaybackStateChanged() } } ※関係ない部分は省略 }
単純に、GCDを使って遅延実行しているだけ。無駄に[weak self]を指定してあるのは、単なる個人的な趣味。
ミュージックプレイヤーであれば、一定の間隔でタイマーを回して何か処理するような実装もよくあるだろうし、そうであれば、そっちで毎回ステータスをチェックするようにすれば、こんな面倒な処理はやらなくて済む。
というか、Apple標準のミュージックアプリがその形になってるから、この部分のバグを直す気にならないんだろうな・・・
ソースコード
最終的なソースコードはこちら。
See_Ku / MusicPlayerTips — Bitbucket
https://bitbucket.org/See_Ku/musicplayertips
https://itunes.apple.com/jp/app/46-minute-shuffle/id991599315?mt=8&uo=4&at=10l8JW&ct=hatenablog