audioPlayerDidFinishPlaying之后的EXC_BAD_ACCESS:调用

时间:2011-06-21 13:35:08

标签: iphone objective-c delegates avaudioplayer exc-bad-access

我有一个课程,我打电话来使用AVAudioPlayer,在播放音频时一切正常和花花公子,但是当调用-audioPlayerDidFinishPlaying:时我的NSLog()命令说玩家被释放;问题是该应用程序稍后崩溃。我应该提到audioPlayer是本课程中的一个ivar。这是代码:

-(id) initWithFileName:(NSString *)sndFileName
{
    [super init];
    sndFileToPlay = [[NSString alloc] initWithString:sndFileName];
    return self;
}

-(void)dealloc {
    [audioPlayer release];
    self.audioPlayer.delegate = nil;
    self.audioPlayer = nil;
    [super dealloc];
}

-(void)play
{
    [self playSound:sndFileToPlay];
}

-(void)playSound:(NSString *)fileName
{
    NSString *fname, *ext;
    NSRange range = [fileName rangeOfString:@"."];
    int location = range.location;
    if( location > 0 )
    {
        fname = [fileName substringWithRange:NSMakeRange(0, location)];
        ext = [fileName substringFromIndex:location+1];
        [self playSound:fname :ext];
    }
}

-

-(void)playSound:(NSString *)fileName   :(NSString *)fileExt
{
    NSBundle *mainBundle = [NSBundle mainBundle];

    NSURL *fileURL = [NSURL fileURLWithPath:
           [mainBundle pathForResource:fileName ofType:fileExt] isDirectory:NO];

    if (fileURL != nil) 
    {
        audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
                                                             error: nil];

        [fileURL release];
        [audioPlayer setDelegate:self];
        [audioPlayer play];
    }
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
                       successfully:(BOOL)flag
{
    NSLog(@"Releasing"); 
    [audioPlayer release];
}

2 个答案:

答案 0 :(得分:4)

您的代码存在一些问题。

首先,在dealloc

[audioPlayer release];
self.audioPlayer.delegate = nil;
self.audioPlayer = nil;

您正在发布audioPlayer,然后,在发布的(可能已取消分配)播放器上,您将委托设置为nil,然后再将属性设置为再次释放。删除[audioPlayer release];

在你的audioPlayerDidFinishPlaying:successfully:中你也发布了播放器,但你没有将变量设置为nil。这可能会导致崩溃,因为再次访问此变量时,另一个对象可能位于该内存地址。请改用该属性,并按照dealloc

进行操作
self.audioPlayer.delegate = nil;
self.audioPlayer = nil;

然后,在playSound::(argh,非命名的第二个参数!)中,你过度释放fileURL-[NSURL fileURLWithPath:isDirectory:]返回一个自动释放的对象,你可能不会释放它。

最后但也许并非最不重要的是你泄漏sndFileToPlay,你需要在你的dealloc方法中发布它。而不是sndFileToPlay = [[NSString alloc] initWithString:sndFileName];只需sndFileToPlay = [sndFileName copy];

您可能想要了解Objective-C内存管理。一旦你知道了三个或四个经验法则,这并不难。

答案 1 :(得分:0)

您应该清理代码。如果多次调用playSound,则会泄漏AVAudioPlayer。

在你的dealloc中,你应该将[audioPlayer release]放在下面的两行之后。

启用NSZombieEnabled进行调试,并确保在调用didFinish时不释放audioPlayer。