2010-08-27 3 views
3

Je fais un jeu de comptage pour les enfants. Au début, l'enfant est invité à trouver un certain nombre d'éléments, par exemple: "Pouvez-vous trouver cinq vélos". Tout cela est aléatoirement mis en place à partir de tableaux de sons séparés avec des parties de la phrase: "Pouvez-vous trouver" + "5" + "vélos" = trois mp3 séparés. Lorsque l'enfant commence à cliquer sur les éléments, ils disparaissent et la voix compte. "1", "2", "3", "4", "5", et à la fin "vélos".Problème avec AVAudioplayer ou délégué se désallouant prématurément

J'utilise la méthode audioPlayerDidFinishPlaying: delegate pour assembler les sons et ça marche bien ... la plupart du temps. Mais parfois l'application plante, avec une erreur "bad_access". Après avoir utilisé NSZombie j'ai obtenu: - [AVAudioPlayer performSelector: withObject:]: message envoyé à l'instance libérée

Je pense que c'est parce que l'audiopleur lui-même ou le délégué est libéré prématurément.

J'utilise toujours cette fonction pour lire les sons:

-(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"); 

}

Et est ici le délégué (il exécute différentes actions basées sur le son a finnished):

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)which_player successfully:(BOOL)the_flag{ 
NSLog(@"ny lyd?"); 
[self.jenteBilde stopAnimating]; 
if([email protected]"ingenting"){ 
    NSLog(@"ingenting");  
} 
else if([email protected]"lesobjekt"){ 
    NSLog(@"lesobjekt"); 
    [email protected]"ros"; 
    [self spillVoice:[self.objektNedArray objectAtIndex: [self.objektnr intValue]]]; 
    [self.jenteBilde startAnimating]; 
} 
else if([email protected]"introtall"){ 
    NSLog(@"introtall"); 
    [email protected]"introobjekt"; 
    [self spillVoice:[self.telleOppArray objectAtIndex: [self.tilfeldig intValue]]]; 
    [self.jenteBilde startAnimating]; 
} 
else if([email protected]"introobjekt"){ 
    NSLog(@"introobjekt"); 
    [email protected]"ingenting"; 
    [self spillVoice:[self.objektOppArray objectAtIndex: [self.objektnr intValue]]]; 
    [self.jenteBilde startAnimating]; 
} 
else if([email protected]"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)); 
    [email protected]"ingenting"; 
    [self spillVoice:[rosArray objectAtIndex: result]]; 
    [self.jenteBilde startAnimating]; 
} 

}

Il me semble que la autorelease AVaudioplayers hits dans t oo tôt, même si le son n'est pas encore terminé. J'ai essayé de ne pas autoreleasing, et libérant à la place explicitement dans la fonction de délégué. Mais le problème est que le son ne joue pas toujours jusqu'au bout (quand l'enfant trouve un nouvel objet avant que la voix ait fini de lire) ...

Quelqu'un d'entre vous peut-il nous éclairer? Je serais très reconnaissant!

Répondre

0

Vous devez conserver AVAudioPlayer jusqu'à ce que vous ayez terminé. La meilleure façon de le faire serait de rendre votre voicespiller propriété une propriété conservée, et changer votre mise en œuvre à ce qui suit:

-(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"); 
} 

Lorsque vous appelez le mutator de la propriété ([self setVoicespiller:...]), le joueur précédent sera publié et un nouveau sera défini. Ensuite, assurez-vous d'appeler le [voicespiller release] dans votre méthode dealloc.

Questions connexes