听起来令人困惑,但看起来像这样
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 和整个队列的新手,所以也许我误解了,但上述工作不应该吗?
如果我将主队列上的调用更改为同步调用,那么它可以工作。崩溃发生在 subtitleQueue 调用 AVPlayer 的 makePeriodicCall (或类似)时。
如果我将周期性时间观察器添加到主队列而不是自定义串行队列,则异步调用也有效。但是,文档说添加到不同的队列应该没问题。
问题2)当我在这里时,我还有一个关于“捕获” AVPlayer 的部分的问题。捕获这样的变量是否足够安全,或者我是否必须使用 __weak 并确保它在块内不为 NULL?我的情况是包含 AVPlayer 的控制器是单例的,因此它存在于应用程序的整个生命周期中。我认为这使得不使用 __weak 修饰符可以。我这样想对吗?
干杯,感谢您的帮助!
编辑:例外是 EXC_BAD_ACCESS 代码 2,所以不应该访问的是。它发生在运行 _subtitlesQueue 的单独线程上。它发生在调用 [AVPlayerPeriodicCaller _effectiveRateChanged]
在 _subtitlesQueue 上调用外部 dispatch_async 之前、在主队列上调用内部 dispatch_async 之前以及在调用 addPeriodicTimeObserver 之前在主队列上的 dispatch_async 内部之前,我还打印了 capturePlayer 和 _subtitlesQueue 的值(指针值)。他们都是一样的。
EDIT2:如果我在 subtitleQueue 上的周期性时间观察者创建周围添加一个同步块,那么一切正常......
@synchronized(_subtitlesQueue) {
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:subtitleTimeObservedBlock];
}
全部