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.
精彩评论