ややこしいですがこんな感じです
AVPlayer *capturedPlayer = _player;
dispatch_async(_subtitlesQueue, ^{
// Parse the requested subtitle track and create a subtitle time observer
subripString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
subripEntries = [SubRipParser parse:subripString];
if (!subripEntries.count)
return;
dispatch_async(dispatch_get_main_queue(), ^{
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:^(CMTime time){}];
});
});
ボタンがクリックされると、上記のコードが呼び出されます。クラッシュします。私はGCDとキュー全体に不慣れなので、おそらく誤解しているかもしれませんが、上記はうまくいかないでしょうか?
メイン キューの呼び出しを同期に変更すると、機能します。クラッシュは、AVPlayer の makePeriodicCall (など) への呼び出しで、subtitleQueue から発生します。
カスタム シリアル キューの代わりに定期的な時間オブザーバーをメイン キューに追加すると、非同期呼び出しも機能します。ただし、ドキュメントによると、別のキューに追加しても問題ないはずです。
質問 2) そして、私がここにいる間、AVPlayer を「キャプチャ」する部分についても質問があります。そのような変数をキャプチャすることは十分に安全ですか、それとも __weak を使用してブロック内で NULL でないことを確認する必要がありますか? 私の状況では、AVPlayer を含むコントローラーはシングルトンであるため、アプリケーションの存続期間全体にわたって存在します。これにより、__weak 修飾子を使用しなくても問題ないと思います。私はこれを考えるのが正しいですか?
乾杯、助けてくれてありがとう!
編集: 例外は EXC_BAD_ACCESS コード 2 であるため、アクセスしてはならないものです。_subtitlesQueue を実行している別のスレッドで発生します。そして、[AVPlayerPeriodicCaller _effectiveRateChanged] への呼び出しで発生します。
また、_subtitlesQueue で外側の dispatch_async が呼び出される前、メイン キューで内側の dispatch_async が呼び出される前、およびメイン キューで addPeriodicTimeObserver が呼び出される前に、dispatch_async の内部で、capturedPlayer と _subtitlesQueue (ポインター値) の値を出力しました。それらはすべて同じです。
EDIT2:subtitleQueueでの定期的な時間オブザーバーの作成の周りに同期ブロックを追加すると、うまくいきます...
@synchronized(_subtitlesQueue) {
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:subtitleTimeObservedBlock];
}
全て