2012-04-04 3 views
12

Ich versuche, eine App zu erstellen, die Videos aus einer Datei mit AVFoundation spielt. Die Videos werden in einer Ansicht angezeigt, auf die durch Tippen auf eine Zeile in einer übergeordneten Tabellenansicht zugegriffen wird. Die echte App wird für jede Reihe ein Video haben, aber im Moment benutze ich nur eine zum Testen.AVPlayer stürzt nach mehreren playbacks-

Wenn auf dem Simulator ausgeführt wird, ist die App in Ordnung, aber wenn auf dem Gerät (unter IOS 5.1) ausgeführt wird, wird das Video etwa 5 Mal ausgeführt und stürzt dann unvorhersehbar auf verschiedene Arten ab. Am häufigsten werden die Videoansicht lädt aber das Video selbst nicht spielt, aber manchmal ich eine EXC_BAD_ACCESS auf einem coremedia.remote Faden, beschwerte sich über Objekte ohne Autofreigabepool an Ort und Stelle zugeordnet ist. Ich habe einen @autoreleasepool Block hinzugefügt, der den Code einpackt, der den AVPlayer startet, aber das scheint nicht zu helfen.

Ich frage mich, ob was passiert ist, dass GCD erstellt mehrere Threads in der Hauptwarteschlange, um die Elemente zu spielen, aber sie enden nicht.

So ist die entscheidende Frage ist-wie kann ich das überflüssige GCD aufklären fädelt die AVPlayer auf ausgeführt, wenn der Benutzer die Zurück-Taste in den Videoaufrufe so weit wie möglich Ich habe den Beispielcode gefolgt vorgesehen in Apples AVFoundation Dokumentation here ich habe einige Protokollierung hinzugefügt und (wie oben erwähnt) einen @autoreleasepool Block innerhalb einer der GCD Blocks- außer, dass ich den Code nicht geändert haben.

Die viewDidLoad Methode ist wie folgt:

-(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"); 
      } 

     } 
    }); 
}];  

}

Die viewWillDisappear Methode ist:

-(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"); 
    }); 

}

Ich habe kämpfen mit diesem für die meisten heute - jede Hilfe wäre dankbar erhalten

+0

Danke für die Nachfrage! – headkit

Antwort

14

sollten Sie von Superview entfernen Sie zuerst, wie es die Zählung beibehalten reduzieren wird von einem und ARC wird für Sie der Relase kümmern.

wie diese

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

DANKE! Das hat perfekt für mich funktioniert. – theDuncs

+0

Vielen Dank!Ich habe seit mehr als 1 Woche mit diesem kleinen Käfer gekämpft !! Du hast meine Tage gerettet! – Anthony

+0

gut zu wissen - ich bin verrückt mit ARC ... – headkit

5

können Sie Ihre Videoview in einem Ort gehalten verlassen werden? Denn wenn du dies tust, bleiben dein avPlayerItem und dein avPlayer am Leben und entsprechend dem Thema this bist du auf die iOS-Beschränkung für "Render-Pipeline" gekommen, bei der 4 Videos im Speicher bleiben.

Denken Sie daran, dass var auf Null Einstellung tatsächlich entbindet nicht zugrunde liegende Objekt. So kann Ihre

videoView = nil; 

null Wirkung haben.

+0

interessant über iOS-Beschränkung für "Render-Pipeline" mit 4 Videos im Speicher zu wissen! – headkit

+0

Wo müssen wir diese Zeile hinzufügen? Ich füge es bei 'viewDidLoad' hinzu, aber jetzt zeigt es nicht das Video – CGR

+1

@CGR kann sein, wenn Sie Ihren View-Controller mit Video schließen? – faviomob