Проблема с преждевременным выделением AVAudioplayer или делегата - PullRequest
3 голосов
/ 27 августа 2010

Я делаю счетную игру для детей.На старте ребенка просят найти несколько предметов, например: «Можете ли вы найти пять велосипедов».Это все случайно составлено из отдельных массивов звуков с частями предложения: «Можете ли вы найти» + «5» + «велосипеды» = три отдельных mp3-файла.Когда ребенок начинает нажимать на предметы, они исчезают, и голос начинает считать.«1», «2», «3», «4», «5» и, в конце концов, «велосипеды».

Я использую метод audioPlayerDidFinishPlaying: Delegate, чтобы соединить звуки, и это работаетхорошо ... большую часть времени.Но иногда приложение вылетает с ошибкой «bad_access».После использования NSZombie я получил: - [AVAudioPlayer executeSelector: withObject:]: сообщение отправлено на освобожденный экземпляр

Я думаю, это потому, что либо сам аудиоплеер, либо делегат выпущены преждевременно.

Я всегда использую эту функцию для воспроизведения звуков:

-(void)spillVoice:(NSString*) filnavn{
NSString *audioFilePath=[[NSBundle mainBundle] pathForResource:filnavn ofType:@"mp3"];
NSURL *audioFileURL=[NSURL fileURLWithPath:audioFilePath];
self.voicespiller=[[[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil] autorelease];
self.voicespiller.delegate=self;
[self.voicespiller prepareToPlay];
[self.voicespiller play];
NSLog(@"spiller lyden");

}

А вот делегат (он выполняет различные действия в зависимости от того, какой звук закончен):

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)which_player successfully:(BOOL)the_flag{
NSLog(@"ny lyd?");
[self.jenteBilde stopAnimating];
if(self.etterLyd==@"ingenting"){
    NSLog(@"ingenting");    
}
else if(self.etterLyd==@"lesobjekt"){
    NSLog(@"lesobjekt");
    self.etterLyd=@"ros";
    [self spillVoice:[self.objektNedArray objectAtIndex: [self.objektnr intValue]]];
    [self.jenteBilde startAnimating];
}
else if(self.etterLyd==@"introtall"){
    NSLog(@"introtall");
    self.etterLyd=@"introobjekt";
    [self spillVoice:[self.telleOppArray objectAtIndex: [self.tilfeldig intValue]]];
    [self.jenteBilde startAnimating];
}
else if(self.etterLyd==@"introobjekt"){
    NSLog(@"introobjekt");  
    self.etterLyd=@"ingenting";
    [self spillVoice:[self.objektOppArray objectAtIndex: [self.objektnr intValue]]];
    [self.jenteBilde startAnimating];
}
else if(self.etterLyd==@"ros"){
    NSLog(@"ros");  
    NSMutableArray *rosArray=[[NSMutableArray alloc] initWithObjects:@"TT_flott",@"TT_bravo",@"TT_fint",@"TT_du_er_kjempeflink",@"TT_hurra",@"TT_helt_riktig",nil];
    int result=(arc4random() % (rosArray.count));
    self.etterLyd=@"ingenting";
    [self spillVoice:[rosArray objectAtIndex: result]];
    [self.jenteBilde startAnimating];
}

}

Мне кажется, что авто-релиз AVaudioplayers запускается слишком рано, хотя звук еще не закончен.Я попытался не автоматически выпускать, а вместо этого выпустить явно в функции делегата.Но проблема в том, что звук не всегда воспроизводится до конца (когда ребенок находит новый предмет до того, как голос закончит чтение) ...

Может ли кто-нибудь из вас пролить свет на это.Буду очень признателен!

1 Ответ

0 голосов
/ 28 марта 2011

Вам нужно сохранить AVAudioPlayer, пока вы не закончили с ним.Самый простой способ сделать это - сделать ваше свойство voicespiller сохраненным свойством и изменить реализацию следующим образом:

-(void)spillVoice:(NSString*)filnavn {
    // stop any previous player
    [self.voicespiller stop];

    NSString *audioFilePath=[[NSBundle mainBundle] pathForResource:filnavn ofType:@"mp3"];
    NSURL *audioFileURL=[NSURL fileURLWithPath:audioFilePath];

    [self setVoicespiller:[[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil] autorelease];
    self.voicespiller.delegate=self;
    [self.voicespiller prepareToPlay];
    [self.voicespiller play];
    NSLog(@"spiller lyden");
}

Когда вы вызываете мутатор свойства ([self setVoicespiller:...]), предыдущийигрок будет выпущен, и новый будет установлен.Затем просто вызовите [voicespiller release] в вашем методе dealloc.

...