我正在编写一个“叙述者”类型的应用程序,它会按顺序读出段落中的每个句子。为了实现这一点,我有以下几点:
- (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 中注意到,在播放十个句子时,会创建十个 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,可能会避免递归堆栈的堆积。这没有发生,我仍然遇到同样的情况 - 堆栈建立起来,然后一次全部拆除。我该如何解决这个问题?