Iphone 从AVAudioRecorder播放后AVAudioPlayer崩溃

Iphone 从AVAudioRecorder播放后AVAudioPlayer崩溃,iphone,avaudioplayer,exc-bad-access,avaudiorecorder,Iphone,Avaudioplayer,Exc Bad Access,Avaudiorecorder,我有一个按钮,用户点击开始录制,再次点击停止。当它停止时,我希望录制的语音“回声”返回,以便用户可以听到录制的内容。这在第一次使用时效果很好。如果我第三次按下该按钮,它将开始新的录制,当我按下“停止”按钮时,它将与EXC_BAD_访问崩溃 - (IBAction) readToMeTapped { if(recording) { recording = NO; [readToMeButton setTitle:@"Stop Re

我有一个按钮,用户点击开始录制,再次点击停止。当它停止时,我希望录制的语音“回声”返回,以便用户可以听到录制的内容。这在第一次使用时效果很好。如果我第三次按下该按钮,它将开始新的录制,当我按下“停止”按钮时,它将与EXC_BAD_访问崩溃

- (IBAction) readToMeTapped {

        if(recording)

        {
        recording = NO;
        [readToMeButton setTitle:@"Stop Recording" forState: UIControlStateNormal ];    

        NSMutableDictionary *recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
         [NSNumber numberWithFloat: 44100.0],                 AVSampleRateKey,
         [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
         [NSNumber numberWithInt: 1],                         AVNumberOfChannelsKey,
         [NSNumber numberWithInt: AVAudioQualityMax],         AVEncoderAudioQualityKey,
         nil];

        // Create a new dated file
        NSDate *now = [NSDate dateWithTimeIntervalSinceNow:0];
        NSString *caldate = [now description];          
        recordedTmpFile = [NSURL fileURLWithPath:[[NSString stringWithFormat:@"%@/%@.caf", DOCUMENTS_FOLDER, caldate] retain]];
        error = nil;
        recorder = [[ AVAudioRecorder alloc] initWithURL:recordedTmpFile settings:recordSetting error:&error];
        [recordSetting release];
        if(!recorder){
            NSLog(@"recorder: %@ %d %@", [error domain], [error code], [[error userInfo] description]);
            UIAlertView *alert =
            [[UIAlertView alloc] initWithTitle: @"Warning"
                                       message: [error localizedDescription]
                                      delegate: nil
                             cancelButtonTitle:@"OK"
                             otherButtonTitles:nil];
            [alert show];
            [alert release];
            return;
        }


        NSLog(@"Using File called: %@",recordedTmpFile);
        //Setup the recorder to use this file and record to it.

        [recorder setDelegate:self];
        [recorder prepareToRecord];

        [recorder recordForDuration:(NSTimeInterval) 5]; //recording for a limited time

    }
    else
    { // it crashes the second time it gets here!
        recording = YES;            
        NSLog(@"Recording YES Using File called: %@",recordedTmpFile);
        [readToMeButton setTitle:@"Start Recording" forState:UIControlStateNormal ];

        [recorder stop]; //Stop the recorder.

        //playback recording
        AVAudioPlayer * newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedTmpFile error:&error];
        [recordedTmpFile release];

        self.aPlayer = newPlayer;
        [newPlayer release];

        [aPlayer setDelegate:self];
        [aPlayer prepareToPlay];
        [aPlayer play];
        }   
}

- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)sender successfully:(BOOL)flag {

        NSLog (@"audioRecorderDidFinishRecording:successfully:");

        [recorder release];
        recorder = nil;
}
检查调试器时,它会在此处标记错误

@synthesize aPlayer, recorder;

这是我不明白的部分。我认为这可能与释放记忆有关,但我一直很小心。我遗漏了什么吗?

你确定
@property(retain)
不包括非原子的吗?我认为访问这些属性的一些代码可能是从另一个线程执行的。此外,您应该始终使用self.recorder和self.player通过它们的getter访问这些属性,以确保它们在各自的锁中被访问

在做了一段时间之后,我偶然发现了这个。它告诉我AVAudioPlayer在第二次被解除分配,导致了崩溃。那么代表一定已经做了清理?我检查了这个线程,建议代理不要取消分配。但是,如果我删除该行

   [newPlayer release]; 

我的程序有效!读了这篇文章后,我认为我的问题是应该实现
AVAudioPlayerDelegate的-(void)audioplayerdfinishplaying:(AVAudioPlayer*)player成功:(BOOL)flag
方法,并在声音播放完成后在那里释放音频播放器。我是为AVAudioRecorder做的。

您对多线程编程有多熟悉?嗨,卢修斯,我尝试了您的建议,但这不是问题所在。见下文。