2013-04-28 66 views
1

我正在写一个“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,递归堆栈累积可避免。这没有发生,而且我仍然遇到同样的情况 - 堆叠建立起来,然后立即拆除。我该如何解决这个问题?

回答

0

这条线的位置:

AVAudioPlayer* audioInstance = [[AVAudioPlayer alloc] initWithContentsOfURL:[self urlFromSentNo] error:&error]; 

是什么创造 “AVAudioPlayer” 的多个副本。

如果您想节省内存,您需要找出一种方法来重新使用您的“audioInstance”对象,而不是在每次调用该方法时创建一个新对象。

我的建议是将“audioInstance”属性或ivar(实例变量),然后如果它已经存在,当您完成上一个音频文件并重新开始播放时,将其重置为新URL的内容。

+0

以及如何将其重置为不同的内容?我不认为有办法做到这一点,因为你用它初始化。 – 2014-11-20 15:44:46

+0

感谢“-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

+0

这也是我的观点,内容设置。您只需在完成播放时释放audioInstance即可,然后重新开始。你的措词“......重新设置......”可能太模糊。请编辑它我会收回我的投票。 – 2014-11-20 21:43:02