2015-11-27 4 views
2

Я создаю музыкальный плеер в своем приложении iOS, используя AVPlayer. Я слушаю изменения для AVPlayer.status собственности, как это, чтобы знать, когда звук готов к воспроизведению:Состояние AVPlayer обновляется, когда приложение выходит на передний план

player.currentItem!.addObserver(self, forKeyPath: "status", options: .New, context: nil) 

И когда статус .ReadyToPlay я автоматически начать воспроизведение:

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 
     if (keyPath == "status") { 
      if let currentItem = self.player?.currentItem { 
       let status = currentItem.status 
       if (status == .ReadyToPlay) {      
        self.play() 
       } 
      } 
     }   
    } 
} 

Работает отлично. Проблема в том, что если я начну играть музыку в своем приложении, остановите музыку, а затем оставьте приложение и начните играть музыку, например, Spotify, свойство статуса AVPlayer, похоже, снова будет изменено на .ReadyToPlay время моего приложения выходит на передний план, что заставляет наблюдателя стрелять, что, в свою очередь, заставляет музыку снова начать играть.

Я предполагаю, что что-то происходит с экземпляром AVPlayer, когда приложение снова получает фокус, что заставляет свойство статуса изменять/обновлять.

Как предотвратить такое поведение?

ответ

3

Это похоже на ожидаемое поведение. Если вы хотите, чтобы вы только начали воспроизведение при первом изменении состояния AVPlayerItem, удалите наблюдателя после вызова play().

Оговорка: вы должны уже удалить наблюдателя, если на проигрывателе изменен currentItem, поэтому вам нужно будет использовать дополнительный флаг для отслеживания того, наблюдаете ли вы за существующим currentItem.

Владелец игрока будет следить за состоянием

var isObservingCurrentItem = false 

И обновление/проверить это состояние, когда вы добавляете наблюдателю

if currentItem = player.currentItem where isObservingCurrentItem { 
    currentItem.removeObserver(self, forKeyPath:"status") 
} 

player.currentItem!.addObserver(self, forKeyPath: "status", options: .New, context: nil) 
isObservingCurrentItem = true 

Затем вы можете безопасно удалить наблюдателя после того, как игрок готов к игре

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { 

    if let object = object, 
     keyPath = keyPath, 
     currentItem = self.player?.currentItem, 
     status = currentItem.status 
     where status == .ReadyToPlay { 
      self.play() 
      object.removeObserver(self, forKeyPath:keyPath) 
      isObservingCurrentItem = false 
    } 
} 
+0

Спасибо за идею. Я закончил делать check в watchValueForKeyPath, чтобы узнать, были ли старые и новые значения одинаковыми (то есть ReadyToPlay), и если ничего не делать. Но ваше решение, вероятно, лучше :) – andlin

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