我正在写一个“narrator”类型的应用程序,它按顺序读出段落中的每个句子。要做到这一点,我有以下几点:AVAudioPlayer在预期时不释放内存
- (void) startSentPlayLoop {
_isInPlayingLoop = YES;
_currentlyPlayingSentNo=-1;
[self audioPlayerDidFinishPlaying:nil successfully:NO];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
if (_isInPlayingLoop) {
_currentlyPlayingSentNo++;
[LMAudioPlayer playAudioFileForSent:_currentlyPlayingSentNo withDelegateAs:self];
}
}
和文件LMAudioPlayer.m
+ (void) playAudioFileForSent:(int)sentNo withDelegateAs:(id<AVAudioPlayerDelegate>)delegate {
AVAudioPlayer* audioInstance = [[AVAudioPlayer alloc] initWithContentsOfURL:[self urlFromSentNo] error:&error];
audioInstance.delegate = delegate;
[audioInstance play];
}
其所有运作良好。我注意到在Instruments中,玩了10个句子后,创建了10个AVAudioPlayer实例(每个句子都有一个新实例),并且当所有句子都用尽时(有点建立堆栈并最终调用popAll() )。我猜这是因为在audioPlayerDidFinishPlaying方法中,我调用了playAudioFileForSent,它创建了一个递归。为了避免这种情况(我想要一句话完成,释放内存,然后开始下一句),我试着将playAudioFileForSent方法调用移动到单独的循环中,但没有任何变化。下面是我修改后的代码:
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
if (_isInPlayingLoop) {
_currentlyPlayingSentNo++;
[self performSelectorInBackground:@selector(playNextSentenceInLoop:) withObject:nil];
}
}
- (void)playNextSentenceInLoop:(id)sender {
[LMAudioPlayer playAudioFileForSent:_currentlyPlayingSentNo withDelegateAs:self];
}
所以,我心想,如果我让audioPlayerDidFinishPlaying方法的返回,并调用一个新的线程playAudioFileForSent,递归堆栈累积可避免。这没有发生,而且我仍然遇到同样的情况 - 堆叠建立起来,然后立即拆除。我该如何解决这个问题?
以及如何将其重置为不同的内容?我不认为有办法做到这一点,因为你用它初始化。 – 2014-11-20 15:44:46
感谢“-1”@BorisGafurov!如果您查看[AVAudioPlayer文档](https://developer.apple.com/library/ios/documentation/avfoundation/reference/avaudioplayerclassreference/index.html#//apple_ref/doc/uid/TP40008067-CH1-SW10 ),你会发现设置播放器内容的唯一方法就是按照我刚才的建议(内容在'init'时间设置)。您无法重置已经实例化的AVAudioPlayer对象的内容。 – 2014-11-20 19:41:22
这也是我的观点,内容设置。您只需在完成播放时释放audioInstance即可,然后重新开始。你的措词“......重新设置......”可能太模糊。请编辑它我会收回我的投票。 – 2014-11-20 21:43:02