每隔一段时间,当我调用其 play
方法时,AVAudioPlayer
就会崩溃。
我的应用程序是一个游戏,有背景音乐和许多音效。最初,AVAudioPlayer
导致其运行速度非常缓慢。然而,由于它似乎是最简单的声音 API(尤其是对于像我这样的 2D 游戏),我只是决定使用 dispatch_async
同时播放声音。
这带来了相当大的改进,游戏的主线程没有明显的性能损失。但它会导致游戏崩溃。播放时每隔 5 或 10 分钟就会出现异常。
我不明白为什么会发生这种情况。在并发运行之前是否在播放器内部释放了某些内容?或者完全是别的什么?
编辑:
这是我在玩家在游戏中收集硬币时用来播放声音的代码片段。我使用 4 个 AVAudioPlayers
,因此声音可以重叠:
if([coinCollectPlayer isPlaying]){
if([coinCollectPlayer2 isPlaying]){
if([coinCollectPlayer3 isPlaying]){
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[coinCollectPlayer4 play];});
}
else dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[coinCollectPlayer3 play];});
}
else dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[coinCollectPlayer2 play];});
}
else
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){[coinCollectPlayer play];});
最佳答案
你偶尔崩溃的原因是这个结构不健全:
if([coinCollectPlayer isPlaying]){
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[coinCollectPlayer play];
});
}
您正在主线程上检查isPlaying
。那么,您怎么知道从那时到您在后台线程上说 play
之间,您还没有在后台线程上说过 play
呢?你不知道。可以这样想:
if([coinCollectPlayer isPlaying]){
// GREAT BIG HOLE HERE YOU CAN DRIVE A TRUCK THROUGH
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[coinCollectPlayer play];
});
}
您需要使用一致的线程来与音频播放器进行所有通信,并且必须使用锁定/同步来强制一致性,或者必须使用串行队列(DISPATCH_QUEUE_PRIORITY_DEFAULT
不是)。
话虽如此,我认为你所做的事情是错误的。我不认为 AVAudioPlayer 需要或应该在后台线程上使用。
我建议您尝试使用每个 AVAudioPlayer 一次。换句话说,要播放声音,请创建一个 AVAudioPlayer,播放声音,然后将整个东西扔掉。
关于ios - AVAudioPlayer 并发运行时导致异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23146640/