2012-04-04 9 views
12

Estoy intentando crear una aplicación que reproduzca videos desde un archivo usando AVFoundation. Los videos se muestran en una vista a la que se accede tocando una fila en una tabla vista principal. La aplicación real tendrá un video para cada fila, pero en este momento estoy usando solo uno para probar.AVPlayer se bloquea después de varias reproducciones:

Cuando se ejecuta en el simulador, la aplicación está bien, pero cuando se ejecuta en el dispositivo (en ios 5.1) el video se reproduce correctamente unas 5 veces y se cuelga impredeciblemente de varias maneras. Más comúnmente, la vista de video se carga pero el video no se reproduce, pero a veces Obtengo un EXC_BAD_ACCESS en un hilo EXC_BAD_ACCESS, quejándose de objetos asignados sin un grupo de autorrellena en su lugar. He agregado un bloque @autoreleasepool que envuelve el código que inicia el AVPlayer, pero esto no parece ayudar.

Me pregunto si lo que está sucediendo es que GCD está creando múltiples hilos en la cola principal para reproducir los elementos, pero no están terminando.

Así que la pregunta clave IS- ¿Cómo se borran hasta lo superfluo GCD threads que el AVPlayer se está ejecutando en si el usuario pulsa el botón de retroceso en la vista de vídeo medida de lo posible He seguido el código de ejemplo proporcionado en Documentación AVFoundation de Apple here He agregado algunos registros y (como se mencionó anteriormente) un bloque @autoreleasepool dentro de uno de los bloques GCD, aparte de eso, no he cambiado el código.

El método viewDidLoad es el siguiente:

-(void)viewDidLoad{ 
[super viewDidLoad]; 

NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"TestLapCar2Vid" withExtension:@"m4v"]; 
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; 
NSString *tracksKey = @"tracks"; 

[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:tracksKey] completionHandler: 
^{ 
    dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     @autoreleasepool { 
     NSError *error = nil; 
      AVKeyValueStatus status = [asset statusOfValueForKey:tracksKey error:&error]; 

      if(status == AVKeyValueStatusLoaded){ 
       avPlayerItem = [AVPlayerItem playerItemWithAsset:asset]; 
       [avPlayerItem addObserver:self forKeyPath:@"status" 
            options:0 context:&ItemStatusContext]; 

       [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playerItemDidReachEnd:) 
                  name:AVPlayerItemDidPlayToEndTimeNotification object:avPlayerItem]; 

       avPlayer = [AVPlayer playerWithPlayerItem:avPlayerItem]; 
       [videoView setPlayer:avPlayer]; 
       NSLog(@"Asset loaded"); 
       [avPlayer play]; 
      } 
      else{ 
       NSLog(@"The asset's tracks were not loaded"); 
      } 

     } 
    }); 
}];  

}

El método viewWillDisappear es:

-(void)viewWillDisappear:(BOOL)animated{ 
NSLog(@"view will disappear called"); 
[super viewWillDisappear:animated]; 
dispatch_async(dispatch_get_main_queue(), 
    ^{ 
     [avPlayer pause]; 
     [avPlayerItem removeObserver:self forKeyPath:@"status"]; 
     [[NSNotificationCenter defaultCenter]removeObserver:self]; 
     NSLog(@"Race timeline nav controller has %d sub controllers",self.navigationController.childViewControllers.count); 
     avPlayerItem = nil; 
     avPlayer = nil; 
     videoView = nil; 
     dataStore = nil; 
     pkReader = nil; 
     receivedData = nil; 
     revDial = nil; 
     speedDial = nil; 
     mapView = nil; 
     throttle = nil; 
     NSLog(@"releasing stuff"); 
    }); 

}

He estado luchando con esto durante la mayor parte de hoy, cualquier ayuda sería recibida con gratitud

+0

gracias por preguntar! – headkit

Respuesta

14

Primero debe quitar de superview, ya que reducirá el número de retenciones en uno y ARC se encargará de la reposición por usted.

como esto

[videoView removeFromSuperview]; 
[self setVideoView:nil]; 
+0

¡GRACIAS! Esto funcionó perfectamente para mí. – theDuncs

+0

¡Muchas gracias!He estado luchando por más de 1 semana en este pequeño error. ¡Salvaste mis días! – Anthony

+0

bueno saber - Me vuelvo loco con ARC ... – headkit

5

¿Puede ser que deje su videoView retenido en algún lugar? Porque si lo haces, tu avPlayerItem y avPlayer se mantienen activos y de acuerdo con el tema this, llegaste a la limitación de iOS para "render pipeline" con 4 videos en la memoria.

Recuerde que establecer var a nil en realidad no libera el objeto subyacente. Por lo tanto, su

videoView = nil; 

puede tener cero efecto.

+0

¡Interesante para conocer la limitación de iOS para "render pipeline" con 4 videos en la memoria! – headkit

+0

¿Dónde tenemos que agregar esta línea? Lo estoy agregando en 'viewDidLoad' pero ahora no muestra el video – CGR

+1

@CGR ¿puede ser cuando cierras el controlador con video? – faviomob

Cuestiones relacionadas