2016-07-12 6 views
3

Ich muss zu bestimmten Zeitpunkt in Audiofile springen, direkt nachdem es zu spielen beginnt. So verwende ich seekToTime Methode mit Abschluss-HandlerAVPlayer suchen, nachdem es zu spielen beginnt

avPlayer.play() 

...

avPlayer?.seekToTime(jumpTime, completionHandler: { isComplete in 
    if isComplete { 
     MPNowPlayingInfoCenter.defaultCenter().nowPlayingInfo![MPNowPlayingInfoPropertyElapsedPlaybackTime] = CMTimeGetSeconds((self.avPlayer!.currentItem?.currentTime())!) 
    } 
}) 

Das Problem ist, dass es an der Zeit Datei aus dem Internet starten muss spielen. Und aus irgendeinem Grund stürzt die Version von seekToTime mit dem Vervollständigungshandler die App ab, weil sie aufgerufen wird, bevor der avPlayer gestartet wurde. Die Version ohne Abschluss-Handler funktioniert einwandfrei.

Fehler:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'AVPlayerItem cannot service a seek request with a completion handler until its status is AVPlayerItemStatusReadyToPlay.' 

Gibt es eine Möglichkeit, einen Rückruf mit avPlayer.play() zu benutzen?

Antwort

2

Ja, es gibt einen Weg.

Sie müssen Änderungen in Spieler beobachten:

avPlayer?.addPeriodicTimeObserverForInterval(CMTime(value: 1, timescale: 3), queue: dispatch_get_main_queue()) { [weak self] time in 
    self?.handleCallback(time) 
} 

Und Sie dann den Zustand in der Callback-Griff:

func handleCallback(time: CMTime) {  
    if avPlayer?.status == .ReadyToPlay { 
     // place your seek logic here 
    } 
} 
+0

Es hat nicht genau so funktioniert, aber ich habe es funktioniert. Es hat nicht angefangen zu spielen. Also habe ich die seekToTime-Version ohne Completion-Handler verwendet und den Code von dort in handleCallback() platziert – ttrs

+0

Oh ja, macht Sinn. Vergessen Sie nicht, den Beobachter zu entfernen, indem Sie 'avPlayer? .removeTimeObserver (observer)' aufrufen, wenn Sie ihn nicht mehr brauchen :) – fiks

-1

Schauen Sie bitte auf die Antwort des Apple für sie: https://developer.apple.com/library/content/qa/qa1820/_index.html

class MyClass { 

    var isSeekInProgress = false 
    let player = <#A valid player object #> 
    var chaseTime = kCMTimeZero 
    // your player.currentItem.status 
    var playerCurrentItemStatus:AVPlayerItemStatus = .Unknown 

    ... 

    func stopPlayingAndSeekSmoothlyToTime(newChaseTime:CMTime) 
    { 
     player.pause() 

     if CMTimeCompare(newChaseTime, chaseTime) != 0 
     { 
      chaseTime = newChaseTime; 

      if !isSeekInProgress 
      { 
       trySeekToChaseTime() 
      } 
     } 
    } 

    func trySeekToChaseTime() 
    { 
     if playerCurrentItemStatus == .Unknown 
     { 
      // wait until item becomes ready (KVO player.currentItem.status) 
     } 
     else if playerCurrentItemStatus == .ReadyToPlay 
     { 
      actuallySeekToTime() 
     } 
    } 

    func actuallySeekToTime() 
    { 
     isSeekInProgress = true 
     let seekTimeInProgress = chaseTime 
     player.seekToTime(seekTimeInProgress, toleranceBefore: kCMTimeZero, 
       toleranceAfter: kCMTimeZero, completionHandler: 
     { (isFinished:Bool) -> Void in 

      if CMTimeCompare(seekTimeInProgress, chaseTime) == 0 
      { 
       isSeekInProgress = false 
      } 
      else 
      { 
       trySeekToChaseTime() 
      } 
     }) 
    } 

} 
+0

Ein Link zu einer Lösung ist willkommen, aber stellen Sie bitte sicher, dass Ihre Antwort ohne sie nützlich ist: [Kontext hinzufügen der Link] (// meta.stackexchange.com/a/8259), damit Ihre Mitbenutzer eine Vorstellung davon haben, was es ist und warum es da ist. Zitieren Sie dann den relevantesten Teil der Seite, auf die Sie verlinken, falls das Ziel erreicht wird Seite ist nicht verfügbar. [Antworten, die kaum mehr als ein Link sind, können gelöscht werden.] (// stackoverflow.com/help/deleted-answers) –