I have a detailed controller where AVPlayer is created, when I start the player, then I exit the controller and I enter that data about the song is not saved and when I click on play AVPlayer is created again. The question is how to make AVPlayer save all the data and do not have to delete the old player. Gif with the problem below
it is my code:
ViewControllerAudioInfo is controller in which I get data about 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
}
}
And 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
}
}