【问题标题】:Crashes when using AVAudioPlayer on iPhone在 iPhone 上使用 AVAudioPlayer 时崩溃
【发布时间】:2010-06-16 01:56:25
【问题描述】:

我正在尝试使用 AVAudioPlayer 快速连续播放一些声音。当我不那么频繁地调用声音播放函数以便在再次调用该函数之前完全播放声音时,应用程序运行良好。但是,如果我快速连续调用该函数(以便在播放之前的声音时播放声音),应用程序最终会在调用该函数约 20 次后崩溃,并显示消息“EXC_BAD_ACCESS”。这是函数的代码:

NSString *nsWavPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:wavFileName];

AVAudioPlayer* theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:nsWavPath] error:NULL];
theAudio.delegate = self;

[theAudio play];

正如另一个线程中提到的,我实现了以下委托函数:

- (void) audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    if(!flag)
        NSLog(@"audio did NOT finish successfully\n");
    [player release];
}

但在快速调用该函数大约 20 次后,该应用仍然崩溃。知道我做错了什么吗?

【问题讨论】:

    标签: iphone avaudioplayer exc-bad-access


    【解决方案1】:

    首先:确保您没有再次尝试播放已通过[player release]; 发布的声音,如果您这样做了,您将立即收到该错误消息。一旦您释放与特定声音关联的播放器,您将无法再次播放该文件,就像您在此处显示的那样。尝试注释掉那行代码,看看它是否仍然发生。

    我还遇到了一个问题,每次创建新的player 时,AVAudioPlayer 分配 32kb,如果你有足够的声音,你可能会用完内存并崩溃。我非常怀疑这是您的问题,因为它通常不会抛出该错误代码。

    EXC_BAD_ACCESS 通常是因为我在此论坛上看到的大多数情况下尝试访问不再存在的指针(例如您的 player 对象)

    【讨论】:

    • 谢谢罗伯!事实证明,在某些情况下,我正在释放视图本身,这导致了 EXC_BAD_ACCESS,因为声音仍在播放,但它的委托已被释放。我通过在调用 [theAudio play] 之前立即添加 [self retain] 来修复它,然后在 [player release] 之​​后在 audioPlayerDidFinishPlaying 中调用 [self release]。这样就避免了崩溃。
    【解决方案2】:

    我找到了解决这个问题的更好方法。 您只需要激活/停用您的 AVAudioSession。

    例如:在你的 viewDidLoad 方法中放这个:

    NSError *activationError = nil;
    [[AVAudioSession sharedInstance] setActive:YES error:&activationError];
    

    然后,您可以通过以下任何方法播放声音:

    ... some awesome code ...
    self.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:nil];
    [self.audioPlayer setDelegate:self];
    [self.audioPlayer setVolume: 0.7f];
    [self.audioPlayer setNumberOfLoops:0];
    if ([self.audioPlayer prepareToPlay]) {
        [self.audioPlayer play];            
    }
    ....
    

    最后,(无论声音是否播放完毕),当你完成声音后,就这样做:

    // I've made it on the view's callback
    - (void)viewWillDisappear:(BOOL)animated
    {
        [super viewWillDisappear:animated];
    
        [self.audioPlayer stop];
        [self setAudioPlayer:nil];
        NSError *activationError = nil;
        [[AVAudioSession sharedInstance] setActive:NO
                                             error:&activationError];
        .... etc, etc...
    }
    

    仅此而已:) 您的应用不会再因 EXC_BAD_ACCESS 而崩溃。

    希望这对您有所帮助,并避免这种 hacky [自我保留] / [自我释放]

    来自 Apple 的音频会话编程指南: https://developer.apple.com/library/ios/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/ConfiguringanAudioSession/ConfiguringanAudioSession.html

    【讨论】:

    • 非常感谢。节省了我几天的调试时间。必须阅读 Apple 的音频会话编程指南中的“为什么默认音频会话通常不是您想要的”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-25
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多