ios memory-leaks instruments nsurl

ios - Fuga de NSURL y AVAudioPlayer utilizando ARC



memory-leaks instruments (5)

Este es un problema con la propia biblioteca de Apple. Muchas de las publicaciones (en stackoverflow también) han reportado el problema similar. No hay nada que puedas hacer aquí.

Soy runung Instruments en un iPhone 4S. Estoy usando AVAudioPlayer dentro de este método:

-(void)playSound{ NSURL *url = [self.word soundURL]; NSError *error; audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; if (!error) { [audioPlayer prepareToPlay]; [audioPlayer play]; }else{ NSLog(@"Problem With audioPlayer on general card. error : %@ | url %@",[error description],[url absoluteString]); }

Estoy teniendo fugas al reproducir los archivos de sonido:

Objetos filtrados:

1.

Objeto : NSURL

Biblioteca responsable : Fundación

Marco responsable: Fundación - [NSURL (NSURL) allocWithZone:]

2.

Objeto : _NSCFString

Biblioteca responsable : Fundación

Marco responsable: Fundación - [NSURL (NSURL) initFileURLWithPath:]

Los instrumentos no apuntan directamente a mi código, por lo que me resulta difícil localizar el motivo de la fuga.

MI PREGUNTA

¿Qué podría causar la fuga? O ¿Cómo puedo localizar fugas cuando no soy responsable ante el código?

EDITAR Este es el esquema de la vista de ciclos de instrumentos: Gracias shani


Parece ser una fuga en el código de Apple ... Intenté usar ambos

  • -[AVAudioPlayer initWithData:error:] y
  • -[AVAudioPlayer initWithContentsOfURL:error:]

En el primer caso, la instancia de AVAudioPlayer asignada conserva lo pasado en NSData . En el segundo, se retiene el aprobado en NSURL :

He adjuntado algunas capturas de pantalla de la ventana de Instrumentos que muestran el historial de retener / liberar para un objeto NSData pasado.

Puede ver que el objeto AVAudioPlayer luego crea un objeto C ++ AVAudioPlayerCpp , que retiene el NSData nuevamente:

Más tarde, cuando se AVAudioPlayer objeto AVAudioPlayer se libera el NSData , pero nunca hay una llamada de liberación del AVAudioPlayerCpp asociado ... (Se puede decir de la imagen adjunta)

Parece que tendrás que usar una solución diferente para reproducir medios si quieres evitar filtrar NSData / NSURL''s.

Aquí está mi código de prueba:

-(void)timerFired:(NSTimer*)timer { NSString * path = [[ NSBundle mainBundle ] pathForResource:@"song" ofType:@"mp3" ] ; NSError * error = nil ; NSData * data = [ NSData dataWithContentsOfFile:path options:NSDataReadingMapped error:&error ] ; if ( !data ) { if ( error ) { @throw error ; } } AVAudioPlayer * audioPlayer = data ? [[AVAudioPlayer alloc] initWithData:data error:&error ] : nil ; if ( !audioPlayer ) { if ( error ) { @throw error ; } } if ( audioPlayer ) { [audioPlayer play]; [ NSThread sleepForTimeInterval:0.75 ] ; [ audioPlayer stop ] ; } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... [ NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector( timerFired: ) userInfo:nil repeats:YES ] ; // ... return YES; }


Según las respuestas anteriores, toda mi propia investigación y las discusiones en los foros de desarrolladores de Apple apuntan a que el problema está presente en las bibliotecas de Apple en las versiones de iOS 6.0, 6.0.1 y, por lo que puedo decir, también en 6.0.2.

iOS 6.1 ha solucionado este problema y ya no puedo ver las fugas.

Lamentablemente, esto significa que si cree que su aplicación se ejecutará en teléfonos que aún ejecutan las versiones 6.0, 6.0.1 o 6.0.2 de iOS, tendrá que hacer soluciones para remediar las fugas en estos casos.

Lo que puede ser bueno es saber que el retenerCuenta para lo que se haya utilizado para inicializar AVAudioPlayer parece ser 1 si todo lo demás se ha borrado según lo previsto.

Mi propia solución es encapsular la reproducción de audio en su propia clase, para lo cual realizo el manejo manual de la memoria utilizando el -fno-objc-arc preprocesador -fno-objc-arc al compilar.

Cuando llegue el momento de liberar todo, me aseguro de obtener el recuento de retención del NSURL que he usado para la inicialización (funcionará igual si se inicializa con NSData) antes de comenzar a publicarlo.

Si todo lo demás se maneja correctamente, en este momento debería ser 1 o 2, así que simplemente libérelo la cantidad correcta de veces.

Además, asegúrese de obtener el recuento de retenciones antes de iniciar el lanzamiento; de lo contrario, intentará acceder a un objeto liberado en las versiones de iOS en las que se solucionó el error.


Si este es realmente un error en la biblioteca de Apple, aquí hay una solución no tan divertida.

Para la clase en cuestión, asegúrese de que no tenga habilitado el arco.

Esto se puede hacer yendo a las fases de construcción del objetivo.
Vaya al menú desplegable de fuentes de compilación y encuentre el archivo .m para su clase. ingrese -fno-objc-arc banderas de la columna

Desafortunadamente, tendrá que ajustar la clase y administrar manualmente la memoria.

Una descripción más detallada para configurar una clase para que no esté habilitada para el arco se encuentra en this respuesta en otra pregunta sobre SO

EDITAR

Supongo que podrías encapsular el comportamiento de AVAudioPlayer en otra clase y usar esa clase para toda tu reproducción. En ese caso, podría configurar -fno-objc-arc para un archivo y no tener que trabajar en la administración de la memoria de toda su aplicación.


Tengo entendido que al trabajar en proyectos ARC, usted como desarrollador ya no está a cargo de retenciones / lanzamientos, por lo que el problema está en la biblioteca de Apple y no en su código.