ios - 销毁 Controller 后恢复 avplayer

标签 ios swift audio avplayer swift4

我有一个用于音频播放的静态 AVPlayer,我需要确保在 Controller 被销毁并重播音频后,音频继续播放。我已经尝试了几个月来解决这个问题,但都没有成功,3个月前有人问我一个关于这个主题的问题,到目前为止还没有答案,请帮助一劳永逸地解决这个问题

enter image description here

这是我的代码:

class ViewControllerAudioDetail: UIViewController {

  static var avPlayer = AVPlayer()
  static var status = false
  var timeSlider = false
  fileprivate let seekDuration: Float64 = 10
  fileprivate let seekDurationThirty: Float64 = 30
  var sliderEndTime:Any!
  var sliderDurationTime:Any!



  var mod = [Modal]()

  @IBOutlet weak var ImageView: UIImageView!

  @IBOutlet weak var startTime: UILabel!
  @IBOutlet weak var endTime: UILabel!
  @IBOutlet weak var sliderSong: UISlider!
  @IBOutlet weak var name: UILabel!

  @IBOutlet weak var Volume: UISlider!
  @IBOutlet weak var iconChange: UIButton!


override func viewDidLoad() {
super.viewDidLoad()

  name.text = mod[thisSong].AudioName
  ImageView.image = mod[0].ImageViewAudio

  player(urlSong:mod[thisSong].UrlName!)

  self.timeSlider = true
  ViewControllerAudioDetail.status = true
  Status()
}  


   @IBAction func sliderSong(_ sender: UISlider) {

      //перемотка аудиозвука
      let duration = CMTimeGetSeconds(ViewControllerAudioDetail.avPlayer!.currentItem!.asset.duration)
      let value = sliderSong.value
      let durationToSeek = Float(duration) * value

      ViewControllerAudioDetail.avPlayer?.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),ViewControllerAudioDetail.avPlayer!.currentItem!.duration.timescale)) { [](state) in


        if (self.iconChange.currentImage?.isEqual(UIImage(named: "Play.png")))! {
            ViewControllerAudioDetail.avPlayer?.pause()
        } else if (self.iconChange.currentImage?.isEqual(UIImage(named: "Pause.png")))!{
            ViewControllerAudioDetail.avPlayer?.play()
        }
    }
 }









func Status(){

    timeSlider = false

    if ViewControllerAudioDetail.status == true {
    iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)
    ViewControllerAudioDetail.avPlayer.play()

    } else {

    iconChange.setImage(UIImage(named:"Play.png"), for: .normal)
    ViewControllerAudioDetail.avPlayer.pause()
  }

}


@IBAction func Play(_ sender: Any) {


  if ViewControllerAudioDetail.avPlayer.rate == 0 && ViewControllerAudioDetail.status == false{
      ViewControllerAudioDetail.status = true
      ViewControllerAudioDetail.avPlayer.play()
      ViewControllerAudioDetail.avPlayer.rate = 1.0
      iconChange.setImage(UIImage(named:"Pause.png"), for: .normal)


      if timeSlider == false {

      sliderDurationTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: {
            (CMTime) -> Void in

            self.updateProgressBar()
        })

    }


  } else {

    ViewControllerAudioDetail.status = false
    ViewControllerAudioDetail.avPlayer.rate = 0.0
    ViewControllerAudioDetail.avPlayer.pause()
    iconChange.setImage(UIImage(named:"Play.png"), for: .normal)

  }

}




 func player(urlSong:String) {

    let url = URL(string: urlSong)
    let playerItem = AVPlayerItem(url: url!)

    ViewControllerAudioDetail.avPlayer = AVPlayer(playerItem:playerItem)


NotificationCenter.default.addObserver(self, selector:#selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: playerItem)

sliderDurationTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: {
    (CMTime) -> Void in

    self.updateProgressBar()
})

 sliderEndTime = ViewControllerAudioDetail.avPlayer.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in

    let duration = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer.currentItem!.asset.duration))
    self?.sliderSong.value = Float(CMTimeGetSeconds(time)) / Float(duration)

}


  let duration = CMTimeGetSeconds(ViewControllerAudioDetail.avPlayer.currentItem!.asset.duration)
  let minutesTextOut = Int(duration) / 60 % 60
  let secondsTextOut = Int(duration) % 60
  let strDuration = String(format:"%02d:%02d", minutesTextOut, secondsTextOut)
  endTime.text = strDuration

}


func updateProgressBar(){
    let timeNow = Int(ViewControllerAudioDetail.avPlayer.currentTime().value) / Int(ViewControllerAudioDetail.avPlayer.currentTime().timescale)

  let minutesText = timeNow / 60
  let secondsText = timeNow % 60

  let duration = String(format:"%02d:%02d", minutesText, secondsText)
  startTime.text = duration

}

最佳答案

我猜,你可能有一个静态变量playerDidInit用作保护,然后在第一次初始化AVPlayer时切换true这样的变量。为了能够再次初始化它,如果您想更改 currentSong,那么您可以执行以下操作:

static var playerDidInit = false
static var currentSong:String?
//....//

func player(urlSong:String) {
  if !playerDidInit || urlSong != currentSong {
  playerDidInit = true
  currentSong = urlSong

  let url = URL(string: urlSong)
  let playerItem = AVPlayerItem(url: url!)
  ViewControllerAudioDetail.avPlayer = AVPlayer(playerItem:playerItem)
}

关于ios - 销毁 Controller 后恢复 avplayer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47904955/

相关文章:

javascript - Phonegap PushNotification,如何将我的 Node 推送服务器与phonegap一起使用?

swift - 无法在 IOS10 中锁定一个 View Controller 的旋转

ios - 减缓 Push Segue 的转换

ios - 带有分组 TableView 的 UISearchBar——在 Swift 中

iphone - ios AudioQueue 流式传输多首歌曲

javascript - 加载失败,因为找不到支持的源

ios - 检查用户是否在 UITabBarController 中选择了相同的选项卡

ios - PhotoPicker 示例应用程序,MyViewController

ios - UITableView - 如何隐藏编辑按钮?

javascript - 录制用户的音频并保存到服务器