views:

1273

answers:

1

I have been using a class to play sounds using AVAudioPlayer. Since I want to release these sounds right after they are played, I added a delegate. That causes a "_NSAutoreleaseNoPool(): Object 0x55e060 of class NSCFString autoreleased with no pool in place - just leaking" error right after the sound completes playing, but before my -audioPlayerDidFinishPlaying is called.

Here are some sources:

@interface MyAVAudioPlayer : NSObject <AVAudioPlayerDelegate> {
    AVAudioPlayer *player;
    float   savedVolume;
    BOOL   releaseWhenDone;
}

The main class .m:

- (MyAVAudioPlayer *) initPlayerWithName: (NSString *) name;
{
    NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: name ofType: @"caf"];

    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];

    player = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
    [fileURL release];
    [player prepareToPlay];
    return (self);
}
- (MyAVAudioPlayer *)getAndPlayAndRelease:(NSString *)name withVolume:(float) vol;
{
    MyAVAudioPlayer *newMyAVPlayer = [self initPlayerWithName:name];
    player.volume = vol;
    [player play];
    releaseWhenDone = YES;
    [player setDelegate: self];
    return newMyAVPlayer;
}   
+ (void) getAndPlayAndReleaseAuto:(NSString *)name withVolume:(float) vol;
{
    MyAVAudioPlayer *newMyAVPlayer = [[MyAVAudioPlayer alloc] getAndPlayAndRelease:name withVolume:vol];
//  [newMyAVPlayer autorelease];
}

#pragma mark -
#pragma mark AVAudioPlayer Delegate Methods

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)playedPlayer successfully:(BOOL)flag {
    if (releaseWhenDone) {
     NSLog(@"releasing");
     [playedPlayer release];
//   [self release];
     NSLog(@"released");
    }
}

- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
    NSLog(@"Error while decoding: %@", [error localizedDescription] );
}

- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
    NSLog(@"Interrupted!");
}

- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player {
    NSLog(@"EndInterruption!");
}

- (BOOL) play;
{   
    player.currentTime = 0.0;
    return [player play];
}

Commenting out the [player setDelegate: self]; makes the error go away, but then my audioPlayerDidFinishPlaying doesn't get called.

Any thoughts? Am I suddenly running in another thread?

A: 

I found the problem. My bug, of course.

In a lot of my class files, I was adding:

-(BOOL) respondsToSelector:(SEL) aSelector
{
    NSLog(@"Class: %@ subclass of %@, Selector: %@", [self class], [super class], NSStringFromSelector(aSelector));
    return [super respondsToSelector:aSelector];

}

Mainly out of curiousity.

Well, when I added a delegate to my sound, then this method gets called before the delegate, and it gets called from whatever runloop the AVAudioPlayer happened to be in, and likely, a runloop with no autorelease pool.

mahboudz