2012-04-04 25 views
12

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

+0

grazie per avermelo chiesto! – headkit

risposta

14

Si consiglia di rimuovere prima dal superview in quanto ridurrebbe il conteggio dei ritardi di uno e ARC si prenderà cura del relase per voi.

come questo

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

GRAZIE! Ha funzionato perfettamente per me. – theDuncs

+0

Grazie mille!Ho lottato per più di 1 settimana con questo piccolo insetto !! Hai salvato i miei giorni! – Anthony

+0

buono a sapersi - mi arrabbio con ARC ... – headkit

5

Potresti lasciare il tuo videoVisualizzato in qualche posto? Perché se lo fai, avPlayerItem e avPlayer rimangono in vita e in base all'argomento this sei arrivato fino alla limitazione iOS per "render pipeline" con 4 video che rimangono in memoria.

Ricordare che l'impostazione var a nil non rilascia in realtà l'oggetto sottostante. Quindi il tuo

videoView = nil; 

può avere un effetto zero.

+0

interessante sapere della limitazione di iOS per "render pipeline" con 4 video in memoria! – headkit

+0

Dove dobbiamo aggiungere questa linea? Lo sto aggiungendo a 'viewDidLoad' ma ora non mostra il video – CGR

+1

@CGR potrebbe essere quando chiudi controller di visualizzazione con video? – faviomob

Problemi correlati