开发者

EXC_BAD_ACCESS after audioPlayerDidFinishPlaying: called

I have a class that I call to utilize AVAudioPlayer and everything works fine and dandy when it comes to playing the audio, but when the -audioPlayerDidFinishPlaying: is called my NSLog() command says that the player is released; the problem is that the app crashes moments later. I should mention that audioPlayer is an ivar in this class. Here is the code:

-(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];
}


There are several things wrong with your code.

For one, in your dealloc:

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

You are releasing the audioPlayer, then, on the released (and maybe deallocated) player you set the delegate to nil and then the property, which releases it again. Remove the [audioPlayer release];.

In your audioPlayerDidFinishPlaying:successfully: you're releasing the player as well, but you haven't set the variable to nil. That might cause a crash since by the time you access this variable again a different object might be at that memory address. Use the property instead and do it like in your dealloc:

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

Then, in playSound:: (argh, non-named second argument !) you over-release fileURL. The -[NSURL fileURLWithPath:isDirectory:] returns an autoreleased object, you may not release it.

Last but maybe not least you leak sndFileToPlay, you need to release it in your dealloc method. And instead of sndFileToPlay = [[NSString alloc] initWithString:sndFileName]; simply do sndFileToPlay = [sndFileName copy];.

You might want to read up on Objective-C memory management. It's not hard once you know the three or four rules-of-thumb.


You should clean up your code. If playSound is called several times, you are leaking AVAudioPlayer.

In your dealloc, you should put [audioPlayer release] after the two lines beneath.

Turn on NSZombieEnabled to debug, and make sure that the audioPlayer is not released when didFinish is called.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜