It sounds confusing but it looks like this
这看起来很混乱,但看起来像这样
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){}];
});
});
The above piece of code is called when a button is clicked. It crashes. I'm new to GCD and the whole queue thing so perhaps I'm misunderstanding, but shouldn't the above work?
单击按钮时会调用上面的代码。它崩溃了。我是新手GCD和整个队列的事情,所以也许我是误解,但不应该上面的工作吗?
If I change the call on the main queue to a synchronous then it works. The crash happens from the subtitleQueue on a call to AVPlayer's makePeriodicCall (or the like).
如果我将主队列上的呼叫更改为同步,则它可以正常工作。在调用AVPlayer的makePeriodicCall(或类似函数)时,从subtitleQueue发生崩溃。
The async call also works if I add the periodic time observer to the main queue instead of custom serial queue. However, the docs say that adding on a different queue should be ok.
如果我将周期性时间观察器添加到主队列而不是自定义串行队列,则异步调用也可以。但是,文档说添加不同的队列应该没问题。
Question 2) And while I'm here, I also have a question about the part that "captures" the AVPlayer. Is capturing the variable like that safe enough or do I have to use __weak and make sure it's not NULL within the block? My situation is such that the controller that contains the AVPlayer is a singleton, so it exists throughout the lifetime of the application. I think this makes not using the __weak modifier ok. Am I correct in thinking this?
问题2)当我在这里时,我也有一个关于“捕获”AVPlayer的部分的问题。是否足够安全地捕获变量或者我是否必须使用__weak并确保它在块内不是NULL?我的情况是包含AVPlayer的控制器是一个单独的,因此它在应用程序的整个生命周期中都存在。我认为这不会使用__weak修饰符。我在想这个是正确的吗?
Cheers, and thanks for any help!
干杯,谢谢你的帮助!
EDIT: The exception is a EXC_BAD_ACCESS code 2, so something which shouldn't be accessed is. It happens on a separate thread that is running the _subtitlesQueue. And it happens on a call to [AVPlayerPeriodicCaller _effectiveRateChanged]
编辑:例外是EXC_BAD_ACCESS代码2,所以不应该访问的是。它发生在运行_subtitlesQueue的单独线程上。它发生在[AVPlayerPeriodicCaller _effectiveRateChanged]的调用上
I also printed out the values for the capturedPlayer and _subtitlesQueue (pointer values) before the outer dispatch_async is called on the _subtitlesQueue, before the inner dispatch_async is called on the main queue and inside the dispatch_async on the main queue before the addPeriodicTimeObserver is called. They are all the same.
在调用addPeriodicTimeObserver之前,在主队列上调用内部dispatch_async之前和主队列上的dispatch_async之前,我还在_subtitlesQueue上调用外部dispatch_async之前打印出capturePlayer和_subtitlesQueue(指针值)的值。他们都是一样的。
EDIT2: If I add a synchronized block around the periodic time observer creation on the subtitleQueue then things work...
EDIT2:如果我在subtitleQueue上创建周期性时间观察器周围添加一个synchronized块,那么事情就可以了......
@synchronized(_subtitlesQueue) {
_subtitlesTimeObserver = [capturedPlayer addPeriodicTimeObserverForInterval:CMTimeMake(1, 5)
queue:_subtitlesQueue
usingBlock:subtitleTimeObservedBlock];
}
All
所有
1 个解决方案
#1
1
There seems to be a bug that causes EXC_BAD_ACCESS in -[AVPlayerPeriodicCaller _effectiveRateChanged]
when you add a periodic observer to a playing AVPlayer. The workaround that I'm using is:
当您向播放AVPlayer添加周期性观察者时,似乎有一个错误导致EXC_BAD_ACCESS - [AVPlayerPeriodicCaller _effectiveRateChanged]。我正在使用的解决方法是:
BOOL playing = player.rate > 0.0f;
if (playing)
{
[player pause];
}
[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];
if (playing)
{
[player play];
}
As you pointed out, another workaround is to pass NULL
instead of a serial queue, since that has the effect of enqueueing the blocks on the main thread dispatch queue.
正如您所指出的,另一种解决方法是传递NULL而不是串行队列,因为它具有在主线程调度队列上排队块的效果。
#1
1
There seems to be a bug that causes EXC_BAD_ACCESS in -[AVPlayerPeriodicCaller _effectiveRateChanged]
when you add a periodic observer to a playing AVPlayer. The workaround that I'm using is:
当您向播放AVPlayer添加周期性观察者时,似乎有一个错误导致EXC_BAD_ACCESS - [AVPlayerPeriodicCaller _effectiveRateChanged]。我正在使用的解决方法是:
BOOL playing = player.rate > 0.0f;
if (playing)
{
[player pause];
}
[player addPeriodicTimeObserverForTimeInterval:myTime queue:mySerialQueue usingBlock:myBlock];
if (playing)
{
[player play];
}
As you pointed out, another workaround is to pass NULL
instead of a serial queue, since that has the effect of enqueueing the blocks on the main thread dispatch queue.
正如您所指出的,另一种解决方法是传递NULL而不是串行队列,因为它具有在主线程调度队列上排队块的效果。