4

我有一系列需要连续播放的短(1 秒)声音片段。为此目的正在开发一个类。我正在使用以下代码:

- (void) playClip: (NSData *)clipToPlay
{
    NSError *error = nil;
    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData: clipToPlay error:&error];
    audioPlayer.numberOfLoops = 0;
    audioPlayer.volume = 1.0f;
    [audioPlayer prepareToPlay];

    if (audioPlayer == nil)
        NSLog(@"%@", [error description]);
    else
        [audioPlayer play];
}

可以看出,clipToPlay包含一个声音剪辑为NSData. 这段代码的行为很奇怪。如果我在调试器中运行它并在以下行设置断点:

[audioPlayer play];

剪辑按预期播放 - 调试器在线路上暂停,当您逐步通过线路时,剪辑可以完美播放。但是,如果我去掉断点,它根本不会播放。

我尝试先将其复制NSData到临时文件,结果完全相同。我还clipToPlay以相同的结果复制到另一个变量(使用副本,而不仅仅是指针分配)(我在想也许 clipToPlay 在某个地方被破坏了)。我没有记录错误。

我真的很困惑为什么在播放方法上暂停调试器会导致这种情况发生。有什么建议或想法吗?

4

1 回答 1

5

好的,我发现了这个问题,所以我会回答我自己的问题,所以也许它会为其他人节省一些时间。

问题是 AVAudioPlayer 在有机会播放声音之前就被释放了。当在断点处停止时,显然有机会在声音被释放之前播放声音。

在这种情况下,因为它在它自己的子类中,所以我将 audioPlayer 设为 ivar,并在调用视图控制器中将保存对子类的引用的变量设为 ivar。这可以防止在未播放声音时重新分配。

在子类中,我将委托方法中的 audioPlayer 指针设为 nil:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

我不确定这种安排的最终形式是什么,但这至少解释了导致问题的原因。AVAudioPlayer 实例必须在其范围内,直到声音完成播放,否则 ARC 将释放它。

于 2013-09-17T06:50:59.973 回答