2010-02-04 6 views
0

J'ai posté une question beaucoup plus longue il y a quelques minutes, et comme cela se passe habituellement dès que je l'ai posté j'ai réalisé ce qui se passait, donc je l'ai supprimé car la plupart du post était hors de propos . Puis je suis retourné à Google.iPhone: gestion de la mémoire AVAudioPlayer/NSURL

Il s'avère que j'ai presque le même problème exact que décrit dans ce post, sans réponse à partir de Juin. http://www.iphonedevsdk.com/forum/iphone-sdk-development/20975-avaudioplayer-nsurl-memory-management.html

En résumé: J'utilise AVAudioPlayer et je le libère avec la méthode audioPlayerDidFinishPlaying: successfully: delegate. Après avoir initialisé le lecteur, son objet NSURL associé doit être libéré, sinon il fuit. Mais quand je le relâche après l'initialisation du lecteur, il se bloque car il a déjà été libéré. Ce qui est bizarre, c'est que ça ne plante pas toujours la première fois, la plupart du temps il se bloque après que le second son a été joué. Parfois (rarement) cela permettra à une poignée ou à des joueurs d'être alloués/libérés (je réutilise les pointeurs après avoir libéré) avant de planter. De l'aide?

extrait de code: (soundKeyUp est une variable de classe AVAudioPlayer de *, donc pas de déclaration ici)

NSString *soundKeyUpPath = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"soundKeyUp%d", key.tag % 5] ofType:@"wav"]; 
    NSURL *soundKeyUpURL = [[NSURL alloc] initFileURLWithPath:soundKeyUpPath]; 
    soundKeyUp = [[AVAudioPlayer alloc] initWithContentsOfURL:soundKeyUpURL error:nil]; 
    if(soundKeyUp) { 
     [soundKeyUp setDelegate:self]; 
     [soundKeyUp play]; 
    } 
    else { 
     [soundKeyUp release]; 
     soundKeyUp = nil; 
    } 

    [soundKeyUpPath release]; 
    [soundKeyUpURL release]; 

Réponse à Steve Riggins: L'astuce est qu'il ne tombe pas en panne en même temps tous les temps, comme mentionné. Il libère presque toujours correctement la première fois (ou au moins, il ne tombe pas en panne ou ne fuit pas) mais généralement après la deuxième fois que j'alloue/libère le lecteur et l'URL, il se bloque lors de la sortie de l'URL. Parfois, ça va 3, 4, 5+ fois avant de s'écraser, mais c'est toujours le cas.

Répondre

1

Libérez l'URL lorsque vous créez le lecteur. Je fais cela dans mon application et ça fonctionne bien. Pas de fuites, de plantages, etc

AVAudioPlayer *newPlayer = 
     [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL 
               error: nil]; 
     [fileURL release]; 

Et jamais, jamais libérer des objets qui sont contenus par d'autres objets. C'est leur travail, pas le vôtre. Editer: Si votre URL fuit toujours, vous devez regarder ce que vous faites quand vous le créez. Il devrait être quelque chose comme:

NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: [self path]]; 

Suivant les règles de cacao de la propriété, en utilisant une méthode alloc signifie que vous possédez, vous relâchez.

+0

J'ai mis à jour mon message avec mon code actuel et une réponse directe, car je ne pouvais pas l'insérer dans la boîte de commentaires. Je * publie * l'URL lorsque je crée le lecteur, la modification que j'ai apportée à la méthode du délégué était juste un test pour voir ce qui se passait à ce moment-là dans le programme. Et à droite, je ne sais pas libérer des objets contenus par d'autres objets, mais 1) Je ne savais pas avant de chercher qu'AVAudioPlayer gardait le NSURL comme une propriété après l'initialisation, donc j'étais curieux de savoir comment/comment AVAudioPlayer le gérait; et 2) tenter de briser les choses est une excellente façon d'apprendre comment ils fonctionnent. –

+0

D'accord.Vous ne devriez jamais, jamais utiliser quelque chose qui ressemble à ceci: '[[quelque chose nomMéthode]]]. C'est juste des bogues de mémoire fous qui attendent d'arriver. –

+0

else { [version soundKeyUp]; soundKeyUp = nil; } Vous n'avez certainement pas besoin de cela. Si l'objet est nul, pas besoin de le relâcher. Vous devez le libérer dans dealloc. J'utiliserais une propriété retain pour cette ivar afin que dans dealloc vous puissiez facilement self.soundKeyUp = nil. @property (nonatomic, retain) AVAudioPlayer * soundKeyUp; puis en implémentation @synthesize soundKeyUp. SelfsoundKeyUp = [[AVAudioPlayer alloc] .... etc Vous faites probablement quelques erreurs qui compliquent le débogage. Veillez à comprendre chaque étape de chaque allocation. –

0
- (IBAction) playaction { 

     NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"songname" ofType:@"mp3"]; 
     NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath]; 
     self.soundFileURL = newURL; 
     [newURL release]; 
     [[AVAudioSession sharedInstance] setDelegate: self]; 
     [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil]; 

    // Registers the audio route change listener callback function 
    AudioSessionAddPropertyListener (
            kAudioSessionProperty_AudioRouteChange, 
            audioRouteChangeListenerCallback, 
            self 
            ); 

    // Activates the audio session. 

    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError]; 

    AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: soundFileURL error: nil]; 
    self.appSoundPlayer = newPlayer; 
    [newPlayer release]; 
    [appSoundPlayer prepareToPlay]; 
    [appSoundPlayer setVolume: 1.0]; 
    [appSoundPlayer setDelegate: self]; 
    [appSoundPlayer play]; 

} 

Vous devrez utiliser quelque chose de similaire. Ici appSoundPlayer est déclarée dans le fichier d'en-tête comme

AVAudioPlayer *appSoundPlayer; 

propriété située également à lui,

@property(nonatomic, retain)AVAudioPlayer *appSoundPlayer; 

de presse dans la méthode dealloc .. Ceci est la méthode que je suis et havre de paix » J'ai vu des fuites de mémoire