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
gracias por preguntar! – headkit