2016-07-12 3 views
3

Мне нужно перейти к определенному времени в аудиофайле сразу после его начала. Поэтому я использую метод seekToTime с завершения обработчикаAVPlayer ищет сразу после начала игры

avPlayer.play() 

...

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

Проблема заключается в том, что ему нужно время, чтобы начать воспроизведение файла из Интернета. И по какой-то причине версия seekToTime с обработчиком завершения сбрасывает приложение, потому что оно вызывается перед запуском avPlayer. Версия без обработчика завершения работает нормально.

Ошибка:

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

Есть ли способ, чтобы использовать функцию обратного вызова с avPlayer.play()?

ответ

2

Да, есть способ.

Вы должны наблюдать изменения в плеере:

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

А потом обрабатывать состояния в функции обратного вызова:

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

Это не сработало так, но я заработал. Он не начал играть. Поэтому я использовал версию seekToTime без обработчика завершения и поместил код оттуда в handleCallback() – ttrs

+0

О да, имеет смысл. Не забудьте удалить наблюдателя, вызвав «avPlayer ?.removeTimeObserver (observer)», когда вам это больше не нужно :) – fiks

-1

Пожалуйста, смотрите ответ на Apple, для этого: 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

Ссылка на решение приветствуется, но, пожалуйста, убедитесь, что ваш ответ полезен без него: [добавить контекст вокруг ссылка] (// meta.stackexchange.com/a/8259), чтобы у ваших коллег было некоторое представление о том, что это такое и почему оно есть, а затем укажите наиболее релевантную часть страницы, на которую вы ссылаетесь, в случае, если цель страница недоступна. [Ответы, которые немного больше, чем ссылка, могут быть удалены.] (// stackoverflow.com/help/deleted-answers) –

Смежные вопросы