如何在当前正在播放的曲目结束时自动转到下一曲目?

时间:2016-09-10 14:13:34

标签: ios swift avaudioplayer

我对swift很陌生,我希望实现一段代码,帮助我在当前正在播放的歌曲结束时播放下一首歌曲。 我试图在我的“@IBAction func nextAction”中复制代码(工作正常):

@IBAction func nextAction(sender: AnyObject) {
    self.nextTrack()
}

func nextTrack() {

        if trackId == 0 || trackId < 4 {
            if shuffle.on {
                trackId = Int(arc4random_uniform(UInt32(library.count)))
            }else {
                trackId += 1
            }

            if let coverImage = library[trackId]["coverImage"]{
                coverImageView.image = UIImage(named: "\(coverImage).jpg")
            }

            songTitleLabel.text = library[trackId]["title"]
            artistLabel.text = library[trackId]["artist"]

            audioPlayer.currentTime = 0
            progressView.progress = 0

            let path = NSBundle.mainBundle().pathForResource("\(trackId)", ofType: "mp3")

            if let path = path {
                let mp3URL = NSURL(fileURLWithPath: path)

                do {
                    audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
                    audioPlayer.play()

                    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(PlayerViewController.updateProgressView), userInfo: nil, repeats: true)
                    progressView.setProgress(Float(audioPlayer.currentTime/audioPlayer.duration), animated: false)

                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }
        }

}

并试图把它放在像这样的if条件里面(在viewDidLoad中):

if audioPlayer.currentTime >= audioPlayer.duration {
        self.nextTrack()
    }

我没有任何错误,但在运行时此方法无效,歌曲结束时没有播放下一首歌。

为了使情况更清楚,这是我的控制器:

import UIKit
import AVFoundation

class PlayerViewController: UIViewController {

    @IBOutlet weak var coverImageView: UIImageView!
    @IBOutlet weak var progressView: UIProgressView!
    @IBOutlet weak var songTitleLabel: UILabel!
    @IBOutlet weak var artistLabel: UILabel!
    @IBOutlet weak var shuffle: UISwitch!

    var trackId: Int = 0
    var library = MusicLibrary().library
    var audioPlayer: AVAudioPlayer!

    override func viewDidLoad() {
        super.viewDidLoad()


        // Do any additional setup after loading the view.
        if let coverImage = library[trackId]["coverImage"]{
            coverImageView.image = UIImage(named: "\(coverImage).jpg")
        }

        songTitleLabel.text = library[trackId]["title"]
        artistLabel.text = library[trackId]["artist"]

        let path = NSBundle.mainBundle().pathForResource("\(trackId)", ofType: "mp3")

        if let path = path {
            let mp3URL = NSURL(fileURLWithPath: path)

            do {
                audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
                audioPlayer.play()

                NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(PlayerViewController.updateProgressView), userInfo: nil, repeats: true)
                progressView.setProgress(Float(audioPlayer.currentTime/audioPlayer.duration), animated: false)

            } catch let error as NSError {
                print(error.localizedDescription)
            }
        }

    }

    override func viewWillDisappear(animated: Bool) {
        audioPlayer.stop()
    }

    func updateProgressView(){

        if audioPlayer.playing {

            progressView.setProgress(Float(audioPlayer.currentTime/audioPlayer.duration), animated: true)
        }

    }


    @IBAction func playAction(sender: AnyObject) {
        if !audioPlayer.playing {
            audioPlayer.play()
        }

    }

    @IBAction func stopAction(sender: AnyObject) {

        audioPlayer.stop()
        audioPlayer.currentTime = 0
        progressView.progress = 0
    }


    @IBAction func pauseAction(sender: AnyObject) {
        audioPlayer.pause()
    }

    @IBAction func fastForwardAction(sender: AnyObject) {
        var time: NSTimeInterval = audioPlayer.currentTime
        time += 5.0

        if time > audioPlayer.duration {
            stopAction(self)
        }else {
            audioPlayer.currentTime = time
        }

    }

    @IBAction func rewindAction(sender: AnyObject) {
        var time: NSTimeInterval = audioPlayer.currentTime
        time -= 5.0

        if time < 0 {
            stopAction(self)
        }else {
            audioPlayer.currentTime = time
        }
    }

    @IBAction func previousAction(sender: AnyObject) {
        if trackId != 0 || trackId > 0 {
            if shuffle.on {
                trackId = Int(arc4random_uniform(UInt32(library.count)))
            }else {
                trackId -= 1
            }

            if let coverImage = library[trackId]["coverImage"]{
                coverImageView.image = UIImage(named: "\(coverImage).jpg")
            }

            songTitleLabel.text = library[trackId]["title"]
            artistLabel.text = library[trackId]["artist"]

            audioPlayer.currentTime = 0
            progressView.progress = 0

            let path = NSBundle.mainBundle().pathForResource("\(trackId)", ofType: "mp3")

            if let path = path {
                let mp3URL = NSURL(fileURLWithPath: path)

                do {
                    audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
                    audioPlayer.play()

                    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(PlayerViewController.updateProgressView), userInfo: nil, repeats: true)
                    progressView.setProgress(Float(audioPlayer.currentTime/audioPlayer.duration), animated: false)

                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }
        }




    }

    @IBAction func swipeDownAction(sender: AnyObject) {
        self.close()
    }

    @IBAction func closeAction(sender: AnyObject) {
        self.close()
    }

    @IBAction func nextAction(sender: AnyObject) {
        self.nextTrack()
    }

    func close() {
        self.dismissViewControllerAnimated(true, completion: nil)
    }


    func nextTrack() {

        if trackId == 0 || trackId < 4 {
            if shuffle.on {
                trackId = Int(arc4random_uniform(UInt32(library.count)))
            }else {
                trackId += 1
            }

            if let coverImage = library[trackId]["coverImage"]{
                coverImageView.image = UIImage(named: "\(coverImage).jpg")
            }

            songTitleLabel.text = library[trackId]["title"]
            artistLabel.text = library[trackId]["artist"]

            audioPlayer.currentTime = 0
            progressView.progress = 0

            let path = NSBundle.mainBundle().pathForResource("\(trackId)", ofType: "mp3")

            if let path = path {
                let mp3URL = NSURL(fileURLWithPath: path)

                do {
                    audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
                    audioPlayer.play()

                    NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(PlayerViewController.updateProgressView), userInfo: nil, repeats: true)
                    progressView.setProgress(Float(audioPlayer.currentTime/audioPlayer.duration), animated: false)

                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }
        }

    }
}

所有代码都是用Xcode 7.3.1

编写的

1 个答案:

答案 0 :(得分:2)

您应该使用AVAudioPlayer委托方法audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool),该方法在音频播放器播放完声音时调用。

  1. PlayerViewController确认AVAudioPlayerDelegate协议如下:

    class PlayerViewController: UIViewController, AVAudioPlayerDelegate {
    
  2. 请务必将self设置为您创建的audioPlayer的代表,并在您需要的viewDidLoadpreviousActionnextTrack方法中执行此操作添加

    audioPlayer.delegate = self
    

    这一行之后:

    audioPlayer = try AVAudioPlayer(contentsOfURL: mp3URL)
    
  3. 现在您可以使用委托方法知道音频播放完毕并转到下一首曲目,只需在课程中添加:

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
        if flag {
            self.nextTrack()
        } else {
            // did not finish successfully
        }
    }