Создание наблюдателя, чтобы проверить, приостановлено ли воспроизведение MediaPlayerState или нет - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть музыкальное приложение, и я хочу определить, было ли воспроизведение приостановлено, когда приложение было закрыто (из-за события, например, телефонного звонка или из-за того, что AirPods ушло из ушей и т. Д.)

Мой первый подходдолжен был запустить функцию внутри viewWillAppear, которая проверила

if mediaPlayer.playbackState == .paused {
    ...
}

Если она была приостановлена, я обновил изображение кнопки воспроизведения / паузы.Однако это не сработало, кнопка «Воспроизведение / Пауза» по-прежнему отображала «Воспроизведение», даже если она была приостановлена.

Затем я попытался добавить наблюдателя в viewDidLoad

NotificationCenter.default.addObserver(self, selector: #selector(self.wasSongInterupted(_:)), name: UIApplication.didBecomeActiveNotification, object: self.mediaPlayer)

.self.wasSongInterupted Я звоню по номеру

@objc func wasSongInterupted(_ notification: Notification) {
    DispatchQueue.main.async {
        if self.mediaPlayer.playbackState == .paused {
            print("paused")
            self.isPlaying = false
            self.playPauseSongButton.isSelected = self.isPlaying
        } else if self.mediaPlayer.playbackState == .playing {
            self.isPlaying = true
            self.playPauseSongButton.isSelected = self.isPlaying
        }
    }
}

Однако у меня все еще возникает та же проблема.

Как лучше всего определить, воспроизводится ли мой музыкальный проигрыватель или приостанавливается при повторном открытииapp?

Редактировать 1: я редактировал свой код на основе комментариев.

wasSongInterrupted не вызывался, и через точки останова и ошибки я обнаружил, что код в основном не нужен.Я изменил свой код на

func wasSongInterrupted() {
  DispatchQueue.main.async {
    if self.mediaPlayer.playbackState == .interrupted {
      var isPlaying: Bool { return self.mediaPlayer.playbackState == .playing }
    print("Playback state is \(self.mediaPlayer.playbackState.rawValue), self.isPlaying Bool is \(self.isPlaying)")
      self.playPauseSongButton.setImage(UIImage(named: "playIconLight"), for: .normal)
      //self.playPauseSongButton.isSelected = self.isPlaying
    }
  }
}

и внутри моего AppDelegate's applicationDidBecomeActive у меня есть

let mediaPlayerVC = MediaPlayerViewController()
mediaPlayerVC.wasSongInterupted()

Теперь код работает, однако у меня есть проблема.

Если я запускаю следующий код:

if self.mediaPlayer.playbackState == .interrupted {
  print("interrupted \(self.isPlaying)")
}

, а затем позвоню и вернусь в приложение, оно достигнет точки останова.Он будет выводить как прерывистое, так и ложное значение, которое является значением Bool для self.isPlaying

Однако, если я попытаюсь обновить пользовательский интерфейс с помощью

self.playPauseSongButton.isSelected = self.isPlaying

или

self.playPauseSongButton.setImage(UIImage(named: "playIconLight.png"), for: .normal)

Я получаю сообщение об ошибке Thread 1: EXC_BREAKPOINT (code=1, subcode=0x104af9258)

1 Ответ

0 голосов
/ 21 сентября 2018

Вы пытаетесь обновить пользовательский интерфейс игрока с viewWillAppear.От Документация Apple :

viewWillAppear (_:)

Этот метод вызывается перед добавлением представления контроллера представления.в иерархию представления и перед настройкой анимации для отображения представления.

Так что, если ваше приложение было suspended и снова становится active, этот метод не будет вызываться, потому что вашUIViewController уже на Navigations Stack.

Если вы хотите уловить момент, когда ваше приложение переходит в состояние active из suspended, вам нужно использовать AppDelegate.От Документация Apple :

applicationDidBecomeActive (_:)

Этот метод вызывается, чтобы приложение узнало, что оно перемещено изнеактивно для активного состояния.Это может произойти из-за того, что ваше приложение было запущено пользователем или системой.

Поэтому вам нужно использовать этот метод на вашем AppDelegate для обработки приложения и обновления интерфейса.

ОБНОВЛЕНИЕ

Вы говорите, что внутри этого AppDelegate метода вы делаете

let mediaPlayerVC = MediaPlayerViewController()
mediaPlayerVC.wasSongInterupted()

Это неправильно, потому что вы создаете новый контроллер представления.Что вам нужно сделать, это получить доступ к существующему представлению контроллера из стека навигации и обновить его.

Одним из возможных решений является использование NotificationCenter для отправки уведомления.Вы просматриваете контроллер должен быть подписан на это событие, конечно.

Сначала вам нужно создать имя уведомления

extension Notification.Name {
    static let appBecameActive = Notification.Name(rawValue: "appBecameActive")
}

Затем в вас AppDelegate добавить следующий код для публикации ваших уведомленийкогда приложение становится активным

func applicationDidBecomeActive(_ application: UIApplication) {
    NotificationCenter.default.post(name: .appBecameActive, object: nil)
}

И, наконец, по вашему мнению, добавьте контроллер для подписки на уведомления

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(wakeUp),
                                           name: .appBecameActive,
                                           object: nil)
    ...
}

@objc func wakeUp() {
    // Update your UI from here
}

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...