Как определить, какое видео закончилось при использовании нескольких AVPlayer? - PullRequest
0 голосов
/ 09 ноября 2019

Я играю два видео рядом на экране, поэтому у меня есть два экземпляра AVPlayer. Я обнаруживаю конец воспроизведения видео с помощью уведомления, который работает нормально. Мой селектор (playerDidFinishPlaying) вызывается для обоих видео, когда они заканчиваются.

NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: .AVPlayerItemDidPlayToEndTime, object: nil) 

Теперь моя проблема в селекторе (playerDidFinishPlaying), я хочу определить, для какого avplayer он вызван? Как я могу однозначно идентифицировать AVPlayer, чье видео закончилось?

Ответы [ 3 ]

4 голосов
/ 09 ноября 2019

через объект уведомления для однозначной идентификации,

после уведомления .AVPlayerItemDidPlayToEndTime с объектом player.currentItem

NotificationCenter
    .default
    .addObserver(self, 
                 selector: #selector(self.moviePlayBackFinished(sender:)),
                 name: .AVPlayerItemDidPlayToEndTime,
                 object: player.currentItem)

Простой способ:

Следующий код работает, недостатком является то, что когда один игрок заканчивается, метод уведомления будет вызван дважды.

    var player = AVPlayer()
    var playerTwo = AVPlayer()


    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay(_:)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay(_:)), name: .AVPlayerItemDidPlayToEndTime, object: playerTwo.currentItem)

    }


     @objc func playerDidFinishPlay(_ noti: Notification) {
        if let p = noti.object as? AVPlayerItem, p == player.currentItem{
             print("1")
        }

        if let p = noti.object as? AVPlayerItem, p == playerTwo.currentItem{
             print("2")
        }
    }

Путь состояния дорожки:

С уведомлением вы можете видеть, что игрок закончился.

Вам нужно найти игрока.

Игрок должен подчиниться двум правилам, это началось, и все закончилось. .

Используйте var hasPlay: (one: Bool, two: Bool), чтобы найти игрока, который только что играет.

Используйте isPlaying, чтобы найти игрока, больше не играемого.

var player = AVPlayer()
var playerTwo = AVPlayer()

var hasPlay: (one: Bool, two: Bool) = (false, false)


override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay), name: .AVPlayerItemDidPlayToEndTime, object: nil)
    }

    @IBAction func beepPressed(_ sender: UIButton) {
        hasPlay.one = true
        let url = // ...
        player = AVPlayer(url: url!)
        player.play()

    }


    @IBAction func beepPressedTwo(_ sender: UIButton) {
       hasPlay.two = true

       let url = // ...
       playerTwo = AVPlayer(url: url!)
       playerTwo.play()

    }

    @objc func playerDidFinishPlay() {

        if player.isPlaying == false, hasPlay.one == true{
            hasPlay.one = false
            print("1")
        }

        if playerTwo.isPlaying == false, hasPlay.two == true{
            hasPlay.two = false
            print("2")
        }


    }

}




extension AVPlayer {
    var isPlaying: Bool {
        return rate != 0 && error == nil
    }
}
3 голосов
/ 11 ноября 2019

Еще одна идея. Обновлен метод @ black_pearl

Различные регистрации уведомлений, с различными методами уведомлений.

    var player = AVPlayer()
    var playerTwo = AVPlayer()



    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay(_:)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
        NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishMusic(_:)), name: .AVPlayerItemDidPlayToEndTime, object: playerTwo.currentItem)

    }


       @objc func playerDidFinishPlay(_ noti: Notification) {
           if let p = noti.object as? AVPlayerItem, p == player.currentItem {
                print("1")
           }
       }


    @objc func playerDidFinishMusic(_ noti: Notification) {
        if let p = noti.object as? AVPlayerItem, p == playerTwo.currentItem{
            print("2")
        }
    }
1 голос
/ 09 ноября 2019

Обновлен первый метод @ dengST30, с некоторой легкостью.

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

Поэтому необходимо добавить несколько взаимоисключающих.

var player = AVPlayer()
var playerTwo = AVPlayer()

var justEnded: (one: Bool, two: Bool) = (false, false)

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay(_:)), name: .AVPlayerItemDidPlayToEndTime, object: player.currentItem)
    NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlay(_:)), name: .AVPlayerItemDidPlayToEndTime, object: playerTwo.currentItem)
    playButton.tintColor = .systemBlue
}



@objc func playerDidFinishPlay(_ noti: Notification) {
           if let p = noti.object as? AVPlayerItem, p == player.currentItem {

                if justEnded.one == false{
                    print("1")
                }
                justEnded.one.toggle()
           }

           if let p = noti.object as? AVPlayerItem, p == playerTwo.currentItem{
                if justEnded.two == false{
                    print("2")
                }

                justEnded.two.toggle()
           }
       }
...