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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With