###前提・実現したいこと
メモリが解放されているかを確認するobjective-cの命令などがあれば知りたかったのですが、抜本対応まで含めて考えてくださる方もいらっしゃるので、不足していた説明を追加します。
iTunesのような音楽再生アプリを作っております。
自分用のアプリで、公開する予定もなければ家族も友達も使いません。
アプリ内だけで音楽を再生する分にはご指摘にあったようにAVPlayerItemを使って再生すればいいですし、再生の制御をアプリが行っているので、その際にselfなりに現在再生中の曲情報を持たせてそれを使えばいいです。
ただ、iTunesのようにアプリがバックグラウンドになった状態や、iPadの待ち受け状態で曲が終了時に自動的に次の曲に遷移させるにはAVQueuePlayerを使う必要があります。
このAVQueuePlayerは複数の曲(AVPlayerItem)が入ったプレイリストをArrayの形で渡して再生を任せることができます。曲が終われば自動的に次の曲に遷移してくれます。
ただ、欠点としてAVQueuePlayerには曲が終わったことや始まったことなどを検知するようなDelegateが存在しないので、仕方なしに
objc
1 [avPlayerItem addObserver:self 2 forKeyPath:@"status" 3 options:NSKeyValueObservingOptionInitial 4 context:(__bridge void *)(Playlist)];
このような形でAVQueuePlayerに渡すAVPlayerItemそれぞれにaddObserverでstatusプロパティが変更された時にイベントが発生するように細工をしています。これだけでは渡した複数のAVPlayerItemのどの曲でイベントが発生したのかわからないのでPlaylistという曲情報が入ったオブジェクトも一緒に渡しています。
こうすることで、observeValueForKeyPath:ofObject:change:contextが呼ばれた際に曲情報やアートワークなどを更新してiPadなどで現在再生中の内容を表示させることに成功しました。
###発生している問題・エラーメッセージ
ところが、しばらく使っているとたまにですがプレイリスト切り替え時に
Thread 1:EXC_BAD_ACCESS (code=1, address=0x...)
上記のエラーが発生してアプリが異常終了します。
プレイリストの切り替えは以下のような順で処理をしています。
- 再生を停止する
- removeObserverでaddObserverしたものを解除
- PlaylistとAVPlayerItemを解放(ARCなのでnilセット)
- 新しいPlaylistとAVPlayerItemを作成してセット
- 再生開始
ここで、removeObserverして解放した曲のイベントがなぜか発生し、当然ながらすでにARCによって解放されているのでPlaylistにアクセスするとBAD_ACCESSとなります。
どういう条件でremoveObserverした後にイベントが発生するのかわかりません。ただ、何度か使っているうちに発生します。1回目で突然発生することは今の所ありません。
###該当のソースコード
objc
1-(void)observeValueForKeyPath:(NSString *)keyPath 2 ofObject:(id)object 3 change:(NSDictionary *)change 4 context:(void *)context { 5 6 if ([NSStringFromClass([object class]) isEqualToString:@"AVPlayerItem"]) { 7 if ([keyPath isEqualToString:@"status"]) { 8 9 AVPlayerItem *objItemNow = object; 10 11 // invest status 12 if (objItemNow.status == AVPlayerStatusReadyToPlay) { 13 // ここで contextに対してBAD_ACCESS 14 [self onDidPlayToStart:(__bridge Playlist *)(context)]; 15 } 16 } 17 } 18}
###教えて欲しいこと
ARC管理下でcontext内のメモリが自動解放された後にAVPlayerItemにメッセージが飛んできているのが原因と思われますが、(タイミングによってはそうなるのかもしれません)その場合はどうせremoveObserverされた後のAVPlayerItemに対して飛んできた謎イベントなので処理をスキップさせようと思っています。
抜本的な解決法(回避法)もあればお願いいたします。
それと、コメントにあったようにあまり手を加えたくはありません。
今時点で特に歪なことはしておらず、公式のサンプルに毛が生えた程度の処理しかしていないので、これを回避するためだけに根本的に全部作り替えるような対応や、複数の状態管理変数をselfに持たせて歪なフラグコントロールをしてまで改善しようとは思いません。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/11/20 02:03
2016/11/20 02:30
2016/11/20 04:04
2016/11/20 21:54 編集
2016/11/20 23:09
2016/11/21 15:03
2016/11/21 19:30