在销毁控制器后恢复avplayer

时间:2017-12-20 11:26:52

标签: ios swift audio avplayer swift4

我有一个用于音频播放的静态AVPlayer,我需要确保在控制器被销毁并重放音频后,音频会继续播放。我已经尝试了几个月来解决这个问题,但都没有取得任何成功,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

}

1 个答案:

答案 0 :(得分:2)

我想,你可能有一个静态变量playerDidInit用作守卫,然后在你第一次初始化true时切换AVPlayer这样的变量。为了能够再次初始化,如果您想要更改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)
}