使用多个 AVPlayer 时如何检测哪个视频结束了?

How to detect which video ended when using multiple AVPlayers?

我在屏幕上并排播放两个视频,所以我有两个 AVPlayer 实例。我正在使用工作正常的通知检测视频播放结束。我的选择器 (playerDidFinishPlaying) 在两个视频结束时都被调用。

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

现在我的问题出在选择器 (playerDidFinishPlaying) 上,我想检测它是为哪个 avplayer 调用的?如何唯一标识视频结束的AVPlayer?

通过通知对象进行唯一标识,

post 通知 .AVPlayerItemDidPlayToEndTime 对象为 player.currentItem

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

简单的方法:

下面的代码可以,缺点是当一个玩家结束时,notify方法会被调用两次。

    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")
        }
    }

轨道状态方式:

有了Notification,你可以看到,有一个播放器结束了。

你需要找到播放器。

玩家必须遵守两条规则,开始了,结束了。

使用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
    }
}

更新了@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()
           }
       }

另一个想法。更新了@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")
        }
    }