iphone - audioPlayerDidFinishPlaying : called之后的EXC_BAD_ACCESS

标签 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];
}

最佳答案

您的代码存在一些问题。

例如,在您的 dealloc 中:

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

您正在释放audioPlayer,然后,在已释放(可能是已释放)的播放器上,您将委托(delegate)设置为nil,然后将属性设置为nil,这将再次释放它。删除[audioPlayer release];

在您的 audioPlayerDidFinishPlaying:successively: 中,您也释放了播放器,但尚未将变量设置为 nil。这可能会导致崩溃,因为当您再次访问该变量时,该内存地址可能有不同的对象。请使用该属性,并像在 dealloc 中那样执行操作:

self.audioPlayer.delegate = nil;
self.audioPlayer = nil;

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

最后但也许并非最不重要的一点是,您泄漏了 sndFileToPlay,您需要在 dealloc 方法中释放它。而不是 sndFileToPlay = [[NSString alloc] initWithString:sndFileName]; 只需执行 sndFileToPlay = [sndFileName copy];

您可能想阅读有关 Objective-C 内存管理的内容。一旦您了解了三四个经验法则,这就不难了。

关于iphone - audioPlayerDidFinishPlaying : called之后的EXC_BAD_ACCESS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6426133/

相关文章:

ios - 如何同时支持纵向和横向模式 - XIB 的可重用 View

ios - uilabel 文本仅在需要时换行

ios - Facebook 按钮委托(delegate)无法正常工作

objective-c - 使用 Grand Central Dispatch 进行 Internet 请求的良好模式?

iPhone如何检查手机是否可以使用 native 邮件应用程序发送/接收邮件?

objective-c - Objective-C : Delegate method not getting called

.net - 如何在 .NET 中将方法作为参数传递而不声明委托(delegate)

iphone - iPhone/Objective-C-转换语音 “live”

iphone - 如何提高tesseract识别数字的结果

iphone - 屏幕上的 CGRect 网格?