Avplayer创建了2次

时间:2017-07-10 08:18:39

标签: ios swift avplayer

我有一个详细的控制器,其中创建AVPlayer,当我启动播放器,然后我退出控制器,我输入有关该歌曲的数据未保存,当我点击播放AVPlayer再次创建。问题是如何使AVPlayer保存所有数据,而不必删除旧的播放器。 Gif有以下问题

enter image description here

这是我的代码:

ViewControllerAudioInfo是控制器,我在其中获取有关歌曲的数据

 func request(){

    let urlData = "https:---.com/local/apps/apple/library_detail.php/?idLibrary=\(detail!.id!)"


    var urlRequest = URLRequest(url: URL(string: urlData)!)
    urlRequest.timeoutInterval = 300



    let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in

        if error != nil{
            print(error ?? 0)
            return
        }

        DispatchQueue.main.async {

            let json = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String: Any]


            if let posts = json["FILE"] as? [AnyObject] {
                for post in posts {
                    var info = Modal()

                    info.AudioName = post["NAME"] as? String
                    info.UrlName = post["SRC"] as? String
                    info.ImageViewAudio = self.detail?.ImageView
                    info.AudioName = info.AudioName?.replacingOccurrences(of:".mp3", with: "")

                    self.mod.append(info)


                }
            }
        }

    }
    self.preloadEnd()
    task.resume()
}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

     if segue.identifier == "audioDetail" {
        let destinationVC = segue.destination as! ViewControllerAudioDetail
        destinationVC.mod = mod
    }

    if segue.identifier == "list" {
        let destinationVC = segue.destination as! TableViewControllerAudioList
        destinationVC.mod = mod
    }
}

和detailController

import UIKit  
import AVFoundation

class ViewControllerAudioDetail: UIViewController {


static var avPlayer:AVPlayer?
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 menuButton: UIBarButtonItem!


@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()


    //кнопка назад
    let backItem = UIBarButtonItem()
    backItem.title = ""
    navigationItem.backBarButtonItem = backItem

    menu()


    sliderSong.minimumValue = 0
    sliderSong.maximumValue = 1
    sliderSong.setThumbImage(UIImage(named: "thumb.png"), for: .normal)



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

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

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


    do {
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        let _ = try AVAudioSession.sharedInstance().setActive(true)
    } catch let error as NSError {
        print("an error occurred when audio session category.\n \(error)")
    }


}

func menu(){

    if revealViewController() != nil {

        menuButton.target = revealViewController()
        menuButton.action = #selector(SWRevealViewController.rightRevealToggle(_:))

        view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())


    }

}


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


@IBAction func volume(_ sender: UISlider) {

    ViewControllerAudioDetail.avPlayer?.volume = sender.value
}



@IBAction func minusThirtySec(_ sender: Any) {

    let playerCurrentTime = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer?.currentTime())!)
    var newTime = playerCurrentTime - seekDurationThirty

    if newTime < 0 {
        newTime = 0
    }
    let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
    ViewControllerAudioDetail.avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)


}
@IBAction func minusTenSec(_ sender: Any) {

    let playerCurrentTime = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer?.currentTime())!)
    var newTime = playerCurrentTime - seekDuration

    if newTime < 0 {
        newTime = 0
    }
    let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
    ViewControllerAudioDetail.avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

}

@IBAction func plusTenSec(_ sender: Any) {

    guard let duration = ViewControllerAudioDetail.avPlayer?.currentItem?.duration else{
        return
    }
    let playerCurrentTime = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer?.currentTime())!)
    let newTime = playerCurrentTime + seekDuration

    if newTime < (CMTimeGetSeconds(duration) - seekDuration) {

        let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
        ViewControllerAudioDetail.avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

    }

}
@IBAction func plusThirtySec(_ sender: Any) {

    guard let duration = ViewControllerAudioDetail.avPlayer?.currentItem?.duration else{
        return
    }
    let playerCurrentTime = CMTimeGetSeconds((ViewControllerAudioDetail.avPlayer?.currentTime())!)
    let newTime = playerCurrentTime + seekDurationThirty

    if newTime < (CMTimeGetSeconds(duration) - seekDuration) {

        let time2: CMTime = CMTimeMake(Int64(newTime * 1000 as Float64), 1000)
        ViewControllerAudioDetail.avPlayer?.seek(to: time2, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

    }

}

@IBAction func Next(_ sender: Any) {

    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderEndTime)
    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderDurationTime)



    if thisSong == mod.count - 1 {
        thisSong = 0
    } else {
        thisSong += 1
    }


    if thisSong != mod.count{

        name.text = mod[thisSong].AudioName
        player(urlSong:mod[thisSong].UrlName!)

        Status()

    }

}
@IBAction func Back(_ sender: Any) {

    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderEndTime)
    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderDurationTime)



    if thisSong != 0 {
        thisSong -= 1
    } else {
        thisSong = mod.endIndex - 1
    }


        name.text = mod[thisSong].AudioName
        player(urlSong:mod[thisSong].UrlName!)

       Status()




}


func Status(){

    timeSlider = false

    if 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 && status == false{
        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 {

        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 playerDidFinishPlaying(note: NSNotification) {

    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderDurationTime)
    ViewControllerAudioDetail.avPlayer?.removeTimeObserver(sliderEndTime)
    NotificationCenter.default.removeObserver(self)


    if thisSong == mod.count - 1 {
        thisSong = 0
    } else {
        thisSong += 1
    }


    if thisSong != mod.count{

        name.text = mod[thisSong].AudioName
        player(urlSong:mod[thisSong].UrlName!)

        Status()

    }




}


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

}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "toList" {
        let vc = segue.destination as! TableViewControllerAudioList
        vc.mod = mod
    }
}

2 个答案:

答案 0 :(得分:0)

不是全局声明AVPlayer,而是将其声明为ViewControllerAudioDetail上的静态属性,以防止它被去除(因为这是更好的做法):

static var avPlayer:AVPlayer?

然后,您应该根据此ViewControllerAudioDetail.avPlayer的状态恢复播放器视图组件的状态。您可以根据information given here确定是否正在播放,例如,可以使用ViewControllerAudioDetail.avPlayer.currentTime()查找当前时间。

答案 1 :(得分:-1)

以下是检查歌曲是否已播放的代码....

        if  avPlayer != nil {
         if ((avPlayer.rate != 0) && (avPlayer.error == nil)) {
             // No need to initialise player again....
         } else {
             // initialise the code here...
             avPlayer = AVPlayer(playerItem:playerItem)
             avPlayer.play()
             avPlayer.actionAtItemEnd = .advance
             avPlayer.addObserver(self, forKeyPath: "currentItem", options: [.new, .initial] , context: nil)
        }
    }