2017-07-02 56 views
1

我試了幾天,做一個按鈕,其中包括下一首歌曲,但我不能
這裏是我的問題
如何把下一екфсл在點擊按鈕與avPlayer如何在下一個跟蹤AVPlayer

這是我的代碼

class ViewControllerAudioDetail: UIViewController { 


var avPlayer:AVQueuePlayer? 
var status = false 
fileprivate let seekDuration: Float64 = 10 
fileprivate let seekDurationThirty: Float64 = 30 

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

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

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


    let url = URL(string: mod[thisSong].UrlName!) 
    let playerItem = AVPlayerItem(url: url!) 
    avPlayer = AVQueuePlayer(playerItem:playerItem) 


    let _ = avPlayer!.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in 

     let duration = CMTimeGetSeconds((self?.avPlayer!.currentItem!.asset.duration)!) 
     self?.sliderSong.value = Float(CMTimeGetSeconds(time))/Float(duration) 

    } 


    let duration = CMTimeGetSeconds(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 



} 

@IBAction func sliderSong(_ sender: UISlider) { 

     //перемотка аудиозвука 
     let duration = CMTimeGetSeconds(avPlayer!.currentItem!.asset.duration) 
     let value = sliderSong.value 
     let durationToSeek = Float(duration) * value 

     avPlayer?.seek(to: CMTimeMakeWithSeconds(Float64(durationToSeek),avPlayer!.currentItem!.duration.timescale)) { [](state) in 

      if (self.iconChange.currentImage?.isEqual(UIImage(named: "Play.png")))! { 
       self.avPlayer?.pause() 
      } else if (self.iconChange.currentImage?.isEqual(UIImage(named: "Pause.png")))!{ 
       self.avPlayer?.play() 
      } 
     } 
} 


@IBAction func volume(_ sender: UISlider) { 

    avPlayer?.volume = sender.value 
} 



@IBAction func minusThirtySec(_ sender: Any) { 

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

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


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

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

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

} 

@IBAction func plusTenSec(_ sender: Any) { 

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

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

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

    } 

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

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

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

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

    } 

} 

@IBAction func Next(_ sender: Any) { 

    let url = URL(string: mod[thisSong].UrlName!) 
    let playerItem = AVPlayerItem(url: url!) 
    avPlayer = AVQueuePlayer(playerItem:playerItem) 

    avPlayer?.insert(playerItem, after: playerItem) 
    avPlayer?.advanceToNextItem() 


//  if thisSong + 1 > mod.count { 
//   thisSong = 0 
//  } else { 
//   thisSong += 1 
    //  } 
    //  
    //   
    //  if thisSong != mod.count{ 
    //    
//   name.text = mod[thisSong].AudioName 
//   player(urlSong:mod[thisSong].UrlName!) 
//   avPlayer?.play() 
// 
//    
//    
//  } 

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



//  if thisSong != 0{ 
//   thisSong -= 1 
//   name.text = mod[thisSong].AudioName 
//   player(urlSong:mod[thisSong].UrlName!) 
//   avPlayer?.play() 
// 
//    
//  } 

} 




@IBAction func Play(_ sender: Any) { 


    if avPlayer?.rate == 0 { 
     avPlayer?.play() 
     avPlayer?.rate = 1.0 
     iconChange.setImage(UIImage(named:"Pause.png"), for: .normal) 


     avPlayer?.addPeriodicTimeObserver(forInterval: CMTimeMakeWithSeconds(1, 1), queue: nil, using: { 
      (CMTime) -> Void in 

      self.updateProgressBar() 
     }) 



    } else { 
     avPlayer?.rate = 0.0 
     avPlayer?.pause() 
     iconChange.setImage(UIImage(named:"Play.png"), for: .normal) 

    } 

} 


func player(urlSong:String) { 




} 



func updateProgressBar(){ 
    let timeNow = Int(avPlayer!.currentTime().value)/Int(avPlayer!.currentTime().timescale) 

    let minutesText = timeNow/60 
    let secondsText = timeNow % 60 

    let duration = String(format:"%02d:%02d", minutesText, secondsText) 
    startTime.text = duration 

} 

而且tableview從這裏我得到的數據

var thisSong = 0 


class TableViewControllerAudioList: UITableViewController { 


override func viewDidLoad() { 
    super.viewDidLoad() 

    tableView.estimatedRowHeight = 50 
    tableView.rowHeight = UITableViewAutomaticDimension 



} 

override func numberOfSections(in tableView: UITableView) -> Int { 
    // #warning Incomplete implementation, return the number of sections 
    return 1 
} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // #warning Incomplete implementation, return the number of rows 
    return modalsF.count 
} 


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellAudioList 

    cell.name.text = modalsF[indexPath.row].AudioName 
    cell.number.text = "\(indexPath.row + 1)" 

    thisSong = indexPath.row 


    return cell 
} 



override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
    let vc = segue.destination as? ViewControllerAudioDetail 

    vc?.mod = [modalsF[(tableView.indexPathForSelectedRow?.row)!]] 

} 
+0

我已經加了我回答請在您的代碼中添加該方法,它肯定會工作。如果有我想要它的全部例子。 –

+0

@AshokLondhe我已經解決了這個問題,但你的方法也在工作 – Vasya2014

+0

你是對的。兩者都在工作,但我想建議去我的答案,因爲這是優化的代碼。也很容易理解。如果AVPlayer有任何此類問題,請告訴我,我一定會幫助你。謝謝。 –

回答

2

玩5他選擇的/當前歌曲

func play(at index: Int) { 
    audioPlayer.removeAllItems() 
    playerItem = audioItems[index] 
    playerItem?.seek(to: kCMTimeZero) 
    audioPlayer.insert(playerItem!, after: nil) 
    audioPlayer.play() 
    isPlaying = true 

    self.playAllSongsTableView.reloadData() 
} 

要播放的歌曲previuos ....

@IBAction func backWordAction(_ sender: UIButton) { 
    var index = audioItems.index(of: audioPlayer.currentItem!) ?? 0 
    if index > 0 { 
     index = index - 1 
    } 
    play(at: index) 
} 

要播放下一首歌曲....

@IBAction func forwordAction(_ sender: UIButton) { 
    var index = audioItems.index(of: audioPlayer.currentItem!) ?? 0 
    if index < (audioItems.count - 1) { 
     index = index + 1 
    } 
    play(at: index) 

} 
0

使用AVQueuePlayer代替AVPlayer可以讓你直接添加項目;

AVQueuePlayer.insert(item: AVPlayerItem, after: AVPlayerItem?) 
AVQueuePlayer.advanceToNextItem() 

您還可以AVPlayerItems

AVQueuePlayer = AVQueuePlayer(items: [AVPlayerItem]) 
1

在其tableview數組我加func didSelectRowAt中,我寫道,收到的手機號碼

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    thisSong = indexPath.row 

} 

全局計數器初始化播放器並通過數據傳遞給控制器​​通過prepareForSegue

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

    if segue.identifier == "listToDetail"{ 
     let vc = segue.destination as? ViewControllerAudioDetail 
     vc?.mod = mod 
    } 
} 

在我詳細的控制器我創造了一首歌曲兩個按鈕和下一個

var avPlayer:AVPlayer? 

var mod = [Modal]() 


@IBAction func Next(_ sender: Any) { 


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


    if thisSong != mod.count{ 
     avPlayer?.removeTimeObserver(sliderDuration) 

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

     Status() 

    } 

} 

@IBAction func Back(_ sender: Any) { 


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


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

     Status() 




} 

而且功能確定這是球員的狀態和設置相同的數據

func Status(){ 
    if status == true { 
     iconChange.setImage(UIImage(named:"Pause.png"), for: .normal) 
     avPlayer?.play() 
    } else { 
     iconChange.setImage(UIImage(named:"Play.png"), for: .normal) 
     avPlayer?.pause() 
    } 

} 

這裏我創建了一個球員

func player(urlSong:String) { 

    let url = URL(string: urlSong) 
    let playerItem = AVPlayerItem(url: url!) 
    avPlayer = AVPlayer(playerItem:playerItem) 


    sliderDuration = avPlayer!.addPeriodicTimeObserver(forInterval: CMTime(seconds: 1, preferredTimescale: CMTimeScale(NSEC_PER_SEC)), queue: DispatchQueue.main) { [weak self] (time) in 

     let duration = CMTimeGetSeconds((self?.avPlayer!.currentItem!.asset.duration)!) 
     self?.sliderSong.value = Float(CMTimeGetSeconds(time))/Float(duration) 

    } 


    let duration = CMTimeGetSeconds(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 


}