【问题标题】:swift. AVPlayer. How to track when song finished playing?迅速。影音播放器。如何跟踪歌曲何时播放完毕?
【发布时间】:2015-01-06 19:19:53
【问题描述】:

用 Swift 中的 AVPlayer 完成歌曲播放后的东方追踪方式是什么?

avplayer 播放完毕时是否有任何函数被调用,或者我应该将计时器与 avplayer 类引用结合起来?

【问题讨论】:

  • 不要将 AVPlayer 与 AVAudioPlayer 混淆 - 下面的一些答案适用于 AVAudioPlayer。

标签: ios swift avplayer


【解决方案1】:

这样的工作:

func play(url: NSURL) {
    let item = AVPlayerItem(URL: url)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: item)

    let player = AVPlayer(playerItem: item)
    player.play()
}

func playerDidFinishPlaying(note: NSNotification) {
    // Your code here
}

完成后不要忘记移除观察者(或在deinit)!

【讨论】:

  • 当我测试它时,我得到了这个错误:“由于未捕获的异常 'NSInvalidArgumentException' 导致应用程序终止,原因:'-[myApp.MyViewController playerDidFinishPlaying]:无法识别的选择器发送到实例”。你能帮帮我吗?
  • @Llg 忘记了“playerDidFinishPlaying:”中的:
【解决方案2】:

您需要创建一个实现AVAudioPlayerDelegate 协议的对象,并将其用作AVAudioPlayer 对象的委托。然后将它们链接在一起,例如:

audioPlayer = try! AVAudioPlayer(contentsOf: audioFileUrl)
audioPlayer.delegate = self

委托可以实现响应某些事件的方法。当音频播放完毕时触发:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    // ...
}

【讨论】:

  • @Flimm 他使用的是 AVPlayer 而不是 AVAudioPlayer
  • 别忘了添加 class ViewController: AVAudioPlayerDelegate {
  • 很好的答案!我正在使用 AVAudioPlayer,并且代理效果很好
【解决方案3】:

对于 Swift 4.2

func play(url: URL) {
    let item = AVPlayerItem(url: url)
    NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(sender:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)

    let player = AVPlayer(playerItem: item)
    player.play() 
}

@objc func playerDidFinishPlaying(sender: Notification) {
    // Your code here
}

【讨论】:

    【解决方案4】:

    Swift 3 的另一个版本

    NotificationCenter.default.addObserver(self, selector: #selector(self.playerDidFinishPlaying(sender:)), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
    
    func playerDidFinishPlaying(sender: Notification) {
    
        // Do Something
    }
    

    【讨论】:

    • Mike Carpenter,我尝试了您的解决方案,但无法正常工作。请参阅我的代码的下一个“答案”。
    • 您收到什么错误?我在几个项目中有这段代码,它编译和执行没有任何问题。
    【解决方案5】:
    import AVFoundation
    
    var AVPlayerCustom:AVAudioPlayer = AVAudioPlayer()
    
    
    class PlayerModule: NSObject, AVAudioPlayerDelegate {
    
        func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
            print("Finish")
        }
    
        func playWithData(data: Data, proc: Int) {
            //print(data)
    
            do {
    
                AVPlayerCustom = try AVAudioPlayer(data: data)
    
                AVPlayerCustom.delegate = self as! AVAudioPlayerDelegate
    
                AVPlayerCustom.prepareToPlay()
                AVPlayerCustom.play()
    
    
            }
            catch {
                print("error1")
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      这里有一个更完整的解决方案:

      import UIKit
      import AVFoundation
      import MediaPlayer
      
      
      class ViewController: UIViewController,AVAudioPlayerDelegate {
      
          var player: AVAudioPlayer = AVAudioPlayer()
      
          @IBAction func play(_ sender: UIButton) {
              player.play()
              player.currentTime=14*60-10
              print(player.currentTime)
          }
          @IBAction func pause(_ sender: UIButton) {
              player.pause()
          }
          @IBAction func replay(_ sender: UIButton) {
              player.currentTime=0
          }
      
      
          override func viewDidLoad() {
              super.viewDidLoad()
              do{
                  let audioPath = Bundle.main.path(forResource: "elon", ofType: "mp3")
                  player = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: audioPath!))
                  player.prepareToPlay()
                  player.delegate = self
              }
              catch{
                  print(error)
              }
          }
      
          func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool){
              print(flag)
              print("here")
              if flag == true{
      
              }
          }
      
      
      }
      

      【讨论】:

        【解决方案7】:

        对于 Swif3,您需要进行如下更改:

        func play(url: NSURL) {
        let item = AVPlayerItem(URL: url)
          NotificationCenter.default.addObserver(self,selector:Selector("playerDidFinishPlaying"), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
        
        let player = AVPlayer(playerItem: item)
        player.play() 
        }
        
        func playerDidFinishPlaying() {
        // Your code here
        } 
        

        【讨论】:

          【解决方案8】:

          SwiftUI

          在 SwiftUI 中,我不能使用 @objc 函数或委托。 @objc 暴露的函数在结构中不起作用。一种方法是创建一个类或更简单地使用AVAudioPlayer 实例属性isPlaying。 请参阅Apple documentation

          这是我用来检查音频是否播放完毕以相应更新播放/暂停按钮的代码。首先,我将值保存在 @State 属性中:

              @State private var playing: Bool = false
          

          然后在onAppear 中我使用预定的计时器来检查玩家是否还在玩。无论如何我都需要计时器来更新音频的进度。

              .onAppear {
                  [...]
          
                  Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
                          if !audioPlayer.isPlaying {
                              playing = false
                          }
                  }
          

          所以播放/暂停按钮会在曲目播放完毕时自动更新

          Button(action: {
                      if audioPlayer.isPlaying {
                          playing = false
                          self.audioPlayer.pause()
                      } else if !audioPlayer.isPlaying {
                          playing = true
                          self.audioPlayer.play()
                      }
                  }) {
                      Image(systemName: playing ?
                              "pause.circle.fill" : "play.circle.fill")
                          .resizable()
                          .frame(width: 50, height: 50)
                          .aspectRatio(contentMode: .fit)
                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-29
            相关资源
            最近更新 更多