2009-08-29 19 views
6

Estoy atascado en algún extraño problema de fuga de memoria relacionado con el AVAudioPlayer y necesito ayuda después de probar todo lo que se me viene a la mente.AVAudioPlayer memory leak

Aquí está la breve descripción del problema: el código aparece justo después. Inicializo mi reproductor y comienzo a reproducir la pista de sonido en un bucle sin fin (y el bucle sin fin o la reproducción de una vez no cambió el problema). Varios segundos después de que comenzó la música, cambio a otra pista de sonido, por lo tanto creo un nuevo reproductor, lo inicializo, lanzo el anterior (que se está reproduciendo) y luego configuro el nuevo en su lugar y lo reproduzco.

En ese momento (justo después de que llamo al nuevo reproductor - [Player play]) me sale una pérdida de memoria (de 3.5Kb).

He intentado lo siguiente:

  • Detener el antiguo jugador y luego soltarlo - ningún efecto

  • lanzamiento del jugador inmediatamente después de la instrucción de juego - no empezó a jugar

  • Liberar el doble del antiguo reproductor: bloqueo

  • La pérdida de memoria NO ocurre cuando creo y juego el primer jugador!

Además, en la referencia sí dice que el 'juego' es asíncrono y por lo que probablemente aumenta el recuento ref por 1, pero en este caso, ¿por qué no [dejaron Jugador] ayuda?

Gracias,

Aquí están algunas partes del código sobre cómo lo uso:

- (void) loadAndActivateAudioFunction { 
NSBundle  *mainBundle = [NSBundle mainBundle]; 
NSError   *error; 
NSURL   *audioURL = [NSURL fileURLWithPath:[mainBundle pathForResource: Name ofType: Type]]; 
AVAudioPlayer *player = [(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error]; 

if (!player) { 
    DebugLog(@"Audio Load Error: no Player: %@", [error localizedDescription]); 
    DuringAudioPrep = false; 
    return; 
} 
[self lock]; 
[self setAudioPlayer: player]; 
[self ActivateAudioFunction]; 
[self unlock]; 

}

- (void) setAudioPlayer : (AVAudioPlayer *) player { 
if (Player) 
{ 
    if ([Player isPlaying] || Repeat) // The indication was off??? 
     [Player stop]; 
    [Player release]; 
} 
Player = player; 

}

- (void) ActivateAudioFunction { 
[Player setVolume: Volume]; 
[Player setNumberOfLoops: Repeat];  
[Player play]; 

DuringAudioPrep = false; 

}

Respuesta

0

Tu código me parece correcto hasta donde he visto, así que tal vez haya un código en otro lado que está causando el problema.

Diré que estás usando una especie de idioma extraño. En lugar de retener a crear y liberar en el set, me gustaría hacer algo como esto:

// new players will always be created autoreleased. 
    AVAudioPlayer *player = [[(AVAudioPlayer*) [AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:&error] autorelease]; 

- (void) setAudioPlayer : (AVAudioPlayer *) player 
{ 
    if (Player) 
    { 
     if ([Player isPlaying] || Repeat) // The indication was off??? 
      [Player stop]; 
     [Player release]; 
    } 
    Player = [player retain]; 
} 

De esta manera, sólo se conservan objetos "jugador", cuando en realidad entran en su método de setAudioPlayer, lo que podría hacer que sea más fácil para localizar a.

Además, verifique que en realidad se trata de un objeto AVAudioPlayer que está goteando. Los instrumentos deberían poder verificar esto por ti.

+0

Gracias por la respuesta. Sí, he verificado que es el AVAudioPlayer con instrumentos. En cuanto al método, utilizo este porque realmente guardo las diferentes pistas y las vuelvo a usar haciendo coincidir los nombres y si no se están reproduciendo (en lugar de descargar la misma pista varias veces). Como sé que recibo el reproductor de la persona que llama después de hacer un 'Alloc' en él, sé que ya está retenido (a menos que lo haya entendido mal) – Adi

7

Este es un método para crear AVAudioPlayer sin causar pérdidas de memoria. See this page for explaination.

He confirmado en mi aplicación que esto eliminó mi AVAudioPlayer pierde el 100%.

- (AVAudioPlayer *)audioPlayerWithContentsOfFile:(NSString *)path { 
    NSData *audioData = [NSData dataWithContentsOfFile:path]; 
    AVAudioPlayer *player = [AVAudioPlayer alloc]; 
    if([player initWithData:audioData error:NULL]) { 
     [player autorelease]; 
    } else { 
     [player release]; 
     player = nil; 
    } 
    return player; 
} 
+1

Creo que debe escribirse NSData * audioData en el segundo línea ... – SpaceDog

+0

Este código es realmente extraño, no hay razón para dividir las llamadas alloc vs init. Para un mejor enfoque general, consulte http://stackoverflow.com/questions/17603551/arc-forbids-autorelease/17604365#17604365 o simplemente puede agregar la liberación automática en [[[AVAudioPlayer alloc] initWithData: audioData error: NULL] liberación automática ] – MoDJ

-2

Trate de añadir MediaPlayer.framework a su proyecto

+0

'MediaPlayer.framework'? 'AVAudioPlayer' se encuentra en' AVFoundation.framework' y no debe requerir 'MediaPlayer'. ¿Cuidado para elaborar? –

2

Implementar el protocolo y su AVAudioPlayerDelegate audioPlayerDidFinishPlaying método: éxito: a continuación, suelte el jugador objeto de audio

por ejemplo.

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { 
    [player release]; // releases the player object 
}