Sto provando a creare un'applicazione che riproduce video da un file utilizzando AVFoundation
. I video sono mostrati in una vista accessibile toccando una riga in una tabella tableview. La vera app avrà un video per ogni riga, ma al momento ne sto usando solo uno per i test.AVPlayer si arresta in modo anomalo dopo più riproduzioni-
Quando si esegue il simulatore, l'app è ok, ma quando viene eseguito sul dispositivo (in ios 5.1) il video viene riprodotto correttamente per circa 5 volte, quindi si arresta in modo imprevedibile in vari modi. Più comunemente, la visualizzazione del video viene caricata ma il video stesso non viene riprodotto, ma a volte lo Ottiene un EXC_BAD_ACCESS
su un thread coremedia.remote
, lamentando l'assegnazione di oggetti senza pool di autorelease. Ho aggiunto un blocco @autoreleasepool
che avvolge il codice che avvia AVPlayer, ma questo non sembra essere d'aiuto.
Mi chiedo se ciò che sta accadendo è che GCD sta creando più thread sulla coda principale per riprodurre gli elementi, ma non stanno terminando.
Quindi la domanda chiave è-come faccio a cancellare il superfluo GCD filettature AVPlayer è in esecuzione sul se l'utente preme il pulsante indietro nella visualizzazione di video Per quanto possibile ho seguito il codice di esempio fornito in Documentazione AVFoundation
di Apple here Ho aggiunto alcune registrazioni e (come già detto sopra) un blocco @autoreleasepool
all'interno di uno dei blocchi GCD, a parte il fatto che non ho modificato il codice.
Il metodo viewDidLoad
è la seguente:
-(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");
}
}
});
}];
}
Il metodo viewWillDisappear
è:
-(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");
});
}
ho lottato con questo per la maggior parte di oggi - qualsiasi aiuto sarebbe stato ricevuto con gratitudine
grazie per avermelo chiesto! – headkit