简体   繁体   中英

How to track when song is finished AVAudioPlayer

I want to track when playing song is finished. I tried different solutions from the web but they could not solve my problem. I implemented audioPlayerDidFinishPlaying method but it is not working. How can I understand if playing song is finished?

I am playing songs with playSound function

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:

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

How can I solve my problem? How to track when playing song is finished

EDIT: I am adding whole code.

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


}

I solved my problem with help of Leo Dabus . I changed my edited code. I moved player?.delegate = self to playSound func. Finally, it is working.

playSound & audioPlayerDidFinishPlaying function:

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

Do not forget to add AVAudioPlayerDelegate to ViewController!

class ViewController: UIViewController,AVAudioPlayerDelegate {

You are not setting the player's delegate correctly.

In viewDidLoad, your player is going to be nil, so this line:

    player?.delegate = self

Will do nothing (The question mark is optional chaining, so if player == nil, it does nothing.)

You need to set the delegate after loading the player.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM