使用多个 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")
}
}
我在屏幕上并排播放两个视频,所以我有两个 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")
}
}