2017-07-10 4 views
1

Ich habe einen detaillierten Controller, wo AVPlayer erstellt wird, wenn ich den Player starte, dann verlasse ich den Controller und ich gebe diese Daten über das Lied nicht gespeichert ist und wenn ich auf Wiedergabe klicken AVPlayer ist wieder erstellt . Die Frage ist, wie AVPlayer alle Daten speichern und nicht den alten Player löschen muss. Gif mit dem Problem unterAvplayer wird 2 mal erstellt

enter image description here

ist es mein Code:

ViewControllerAudioInfo ist Controller, in dem ich Daten über Songs

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

Und 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

können Sie diesen Code teilen, die Push-Betrieb der Steuerung zeigt? – KKRocks

+0

würde ich gegen einen globalen AV-Player empfehlen. – cloudcal

+0

@KKRocks Ich habe – Vasya2014

Antwort

0

Stattdessen erhalten einen AVPlayer global deklarieren, de clare es als eine statische Eigenschaft auf Ihrem ViewControllerAudioDetail es zu verhindern, dass deinitalised werden (da dies eine bessere Praxis ist):

static var avPlayer:AVPlayer? 

Sie sollten dann den Zustand Ihrer Spieler Ansicht Komponenten wiederherzustellen, basierend auf dem Zustand dieser ViewControllerAudioDetail.avPlayer. Sie können anhand der information given here feststellen, ob es abgespielt wird oder nicht, und können beispielsweise die aktuelle Uhrzeit anhand von ViewControllerAudioDetail.avPlayer.currentTime() ermitteln.

+0

Können Sie es genauer malen? Wo legen Sie die Daten in viewDidLoad fest? Oder wo sonst – Vasya2014

-1

Unten finden Sie den Code zu überprüfen, ob Song bereits abgespielt wird oder nicht ....

 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)) {Bei der Überprüfung bricht die Anwendung ab – Vasya2014

+0

Kannst du das Absturzprotokoll teilen? –

+0

Schwerwiegender Fehler: unerwartet wurde beim Entpacken von Optional nil gefunden Wert – Vasya2014

Verwandte Themen