2016-06-01 3 views
0

In meiner app an einem gewissen Punkt der Benutzer Video-Wiedergabe mit Klopfen auf einem UI-Element aufrufen kann, und dann das folgende Codesegment ausgeführt wird:AVAsset des „isPlayable“/„spielbar“ Prüfblöcke und Verzögerungen UI-Updates

self.loadingView.frame = _frameWhereItShouldBeLocated; 
[self.loadSpinner startAnimating]; // self.loadSpinner is an UIActivityIndicatorView 
self.loadingView.hidden = FALSE; 

AVPlayer *player = [AVPlayer playerWithURL:fileUrl]; // fileUrl is where is the video file is hosted, which is not a local path 

if ([player.currentItem.asset isPlayable]) 
{ 

    if (!self.playerController) { 
     self.playerController = [[AVPlayerViewController alloc] init]; 
     self.playerController.transitioningDelegate = self; 
     self.playerController.modalPresentationStyle = UIModalPresentationCustom; 
    } 

    self.playerController.player = player; 
    self.playerController.showsPlaybackControls = TRUE; 

    [self.navigationController presentViewController:self.playerController animated:YES completion:nil]; 
    [self.playerController.player play]; 

} 

Ich erwarte, dass die Ladeansicht unmittelbar nach dem Tippen des Benutzers sichtbar ist, und nach einiger Zeit wird der Player-Controller dann präsentiert und das Video abspielen. Es kommt jedoch vor, dass es eine erhebliche Verzögerung gibt, bevor die Ladeansicht sichtbar wird. Diese

ist das, was ich erwartet habe:

User tap -> loading view shown -> (some time for loading the video, etc) -> play video 

Stattdessen ist es das, was ich habe:

User tap -> (significant time delay) -> loading view shown -> play video 

Nach einigen Debuggen fand ich, dass die Verzögerung durch den [player.currentItem.asset isPlayable] Anruf verursacht wird, dh die Ladeansicht wird erst sichtbar, nachdem der Anruf zurückgegeben wurde. Ich habe versucht, das Segment unterhalb der Anzeige der Ladeansicht in einen dispatch_async Anruf setzen, aber es macht nicht anders.

Gibt es trotzdem etwas zu handhaben, damit es sich wie erwartet verhält?

Vielen Dank!

+0

Die Antwort ist in der Einführung von AVAsynchronousKeyValueLoading: https://developer.apple.com/library/mac/documentation/AVFoundation/Reference/AVAsynchronousKeyValueLoading_Protocol/index.html –

Antwort

0

Insted von if ([player.currentItem.asset isPlayable])

Kontrolle dieses

if ((player.rate != 0) && (player.error == nil)) { 
    // player is playing 
} 

Oder Sie können wie unter

[player addObserver:self 
       forKeyPath:@"rate" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

Dann Benachrichtigung für rate Eigenschaft hinzufügen prüfen, ob der neue Wert für die beobachteten Rate Null ist, was bedeutet, dass die Wiedergabe aus irgendeinem Grund gestoppt wurde, wie das Erreichen des Endes oder das Abwürgen wegen leerem Puffer.

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary<NSString *,id> *)change 
         context:(void *)context { 
    if ([keyPath isEqualToString:@"rate"]) { 
     float rate = [change[NSKeyValueChangeNewKey] floatValue]; 
     if (rate == 0.0) { 
      // Playback stopped 
     } else if (rate == 1.0) { 
      // Normal playback 
     } else if (rate == -1.0) { 
      // Reverse playback 
     } 
    } 
} 

Für Rate == 0,0 Fall wissen, was genau die Wiedergabe zu stoppen verursacht, können Sie die folgenden Prüfungen tun:

if (self.player.error != nil) { 
    // Playback failed 
} 
if (CMTimeGetSeconds(self.player.currentTime) >= 
    CMTimeGetSeconds(self.player.currentItem.duration)) { 
    // Playback reached end 
} else if (!self.player.currentItem.playbackLikelyToKeepUp) { 
    // Not ready to play, wait until enough data is loaded 
} 

Basierend auf obige Bedingung verstecken Sie Ihre Anzeige Ansicht. Und laden Sie Ihre Anzeige Sicht auf Hauptgewinde.

dispatch_async(dispatch_get_main_queue(), ^{ 
//load spinner 
}); 
Verwandte Themen