如何在歌曲完成时跟踪 AVAudioPlayer

How to track when song is finished AVAudioPlayer

我想在歌曲播放结束时跟踪。我尝试了来自网络的不同解决方案,但它们无法解决我的问题。 我实施了 audioPlayerDidFinishPlaying 方法,但它不起作用。 我怎么知道播放歌曲结束了?

我正在使用 playSound 功能播放歌曲

playSound func:

func playSound(name: String ) {
    guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
        print("url not found")
        return
    }

    do {
        /// this codes for making this app ready to takeover the device audio
        try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
        try AVAudioSession.sharedInstance().setActive(true)

        /// change fileTypeHint according to the type of your audio file (you can omit this)
        player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)
        // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
        player!.play()
    } catch let error as NSError {
        print("error: \(error.localizedDescription)")
    }
}

audioPlayerDidFinishPlaying 函数:

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    print("finished")//It is not working, not printing "finished"
}

我该如何解决我的问题?歌曲播放完毕如何跟踪

编辑: 我正在添加整个代码。

//
//  ViewController.swift

import UIKit
import SwiftVideoBackground
import AudioToolbox
import AVFoundation


class ViewController: UIViewController,AVAudioPlayerDelegate {

    var player: AVAudioPlayer?

    @IBOutlet weak var backgroundVideo: BackgroundVideo!

    @IBOutlet weak var initialLabel: UILabel!

    @IBOutlet weak var statementLabel: UILabel!


    var mp3: [String] = ["turk_milleti_demokrattir","xyz"]
    var fav: [String] = ["0","0"]
    var name: [String] = ["Türk milleti demokrattır","xy"]


    var toggleState = 1


    @IBOutlet weak var playB: UIButton!

    var counter = 0

    var duration = 0.1


    override func viewDidLoad() {
        super.viewDidLoad()

        player?.delegate = self

        playB.setImage(UIImage(named: "playbtn.png"), for: .normal)

        statementLabel.text = name[counter]

       backgroundVideo.createBackgroundVideo(name: "abc", type: "mp4")





    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func likeButton(_ sender: Any) {


        fav[counter] = "1"
        print(fav[0...1])


    }

    @IBAction func playButton(_ sender: Any) {
        let name = mp3[counter]
        playSound(name: name)


        let playBtn = sender as! UIButton
        if toggleState == 1 {
            player?.play()
            toggleState = 2
            playBtn.setImage(UIImage(named: "pausebtn.png"), for: .normal)
        } else {
            player?.pause()
            toggleState = 1
            playBtn.setImage(UIImage(named:"playbtn.png"),for: .normal)
        }  

    }


    @IBAction func nextButton(_ sender: Any) {

        counter = counter + 1

        if counter == mp3.count {
            counter = 0
        }

        toggleState = 2
        playB.setImage(UIImage(named: "pausebtn.png"), for: .normal)

        playSound(name: mp3[counter])

        statementLabel.text = name[counter]

    }





    func playSound(name: String ) {
        guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
            print("url not found")
            return
        }

        do {
            /// this codes for making this app ready to takeover the device audio
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            /// change fileTypeHint according to the type of your audio file (you can omit this)
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)



            // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
            player!.play()
        } catch let error as NSError {
            print("error: \(error.localizedDescription)")
        }
    }

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        print("finished")//It is not working, not printing "finished"
    }


}

我在 Leo Dabus 的帮助下解决了我的问题。 我更改了编辑后的代码。我搬家了 player?.delegate = selfplaySound 功能。终于可以用了。

playSound & audioPlayerDidFinishPlaying 函数:

  func playSound(name: String ) {
        guard let url = Bundle.main.url(forResource: name, withExtension: "mp3") else {
            print("url not found")
            return
        }

        do {
            /// this codes for making this app ready to takeover the device audio
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
            try AVAudioSession.sharedInstance().setActive(true)

            /// change fileTypeHint according to the type of your audio file (you can omit this)
            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)

            player?.delegate = self

            // no need for prepareToPlay because prepareToPlay is happen automatically when calling play()
            player!.play()
        } catch let error as NSError {
            print("error: \(error.localizedDescription)")
        }
    }

    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        print("finished")//It is working now! printed "finished"!
    }

不要忘记将 AVAudioPlayerDelegate 添加到 ViewController!

class ViewController: UIViewController,AVAudioPlayerDelegate {

您没有正确设置玩家的委托。

在 viewDidLoad 中,你的播放器将变为 nil,所以这一行:

    player?.delegate = self

什么都不做(问号是可选的链接,所以如果 player == nil,它什么都不做。)

加载播放器后需要设置delegate