2017-07-10 15 views
1

我有一个详细的控制器,其中AVPlayer创建时,当我启动播放器,然后我退出控制器,我输入关于歌曲的数据没有保存,当我点击播放AVPlayer被再次创建。问题是如何让AVPlayer保存所有数据,而不必删除旧的播放器。 GIF下面Avplayer创建2次

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 
    } 
} 
+0

您可以共享代码显示控制器的推送操作? – KKRocks

+0

我会推荐一个全球AV播放器。 – cloudcal

+0

@KKRocks我添加了 – Vasya2014

回答

0

相反全球宣布AVPlayer,德克莱尔它作为你的ViewControllerAudioDetail静态属性,以防止它被deinitalised(因为这是更好的做法):

static var avPlayer:AVPlayer? 

你应该再恢复你的播放器视图组件在此基础上ViewControllerAudioDetail.avPlayer的状态的状态。例如,您可以根据information given here来确定它是否在播放,并且可以使用ViewControllerAudioDetail.avPlayer.currentTime()找出当前时间。

+0

你能更详细地画它吗?在viewDidLoad中设置数据的位置?或者在其他地方 – Vasya2014

-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) 
     } 
    } 
+0

if((avPlayer.rate!= 0)&&(avPlayer.error == nil)){检查时,应用程序崩溃 – Vasya2014

+0

可以共享崩溃日志 –

+0

致命错误:意外地发现零,而解包一个可选值 – Vasya2014