risa8
risa8

Reputation: 253

How to use audioPlayerDidFinishPlaying multiple times

I created the UIButton with an image on the MainStoryBoard. When I press that button it plays an audio file and while the audio is playing the background color of UIButton changes.

audioPlayerDidFinishPlaying1 is properly called, however audioPlayerDidFinishPlaying2 seems not be called. I appreciate any advise that lead me to solve this problem.

    let url1 = Bundle.main.bundleURL.appendingPathComponent("music1.mp3")
    let url2 = Bundle.main.bundleURL.appendingPathComponent("music2.mp3")

    @IBOutlet weak var yourButton: CustomButton!
    @IBOutlet weak var yourButton2: CustomButton! 

   func Player(url: URL) {
        do {
            try player = AVAudioPlayer(contentsOf:url)
            player.play()
            yourButton.isSelected = true
            player.delegate = self
        } catch {
            print(error)
        }
    }

    func Player1(url: URL) {
        do {
            try player = AVAudioPlayer(contentsOf:url)
            player.play()
            yourButton2.isSelected = true
            player.delegate = self
        } catch {
            print(error)
        }
    }
    @IBAction func pushButton1(sender: UIButton) {
        Player(url: url1)
    }
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        yourButton.isSelected = false

    }

    @IBAction func pushButton2(sender: UIButton) {
        Player1(url: url2)
    }
    func audioPlayerDidFinishPlaying2(_ player: AVAudioPlayer, successfully flag: Bool) {
        yourButton2.isSelected = false
    }

Upvotes: 2

Views: 974

Answers (1)

giorashc
giorashc

Reputation: 13713

You are creating the player locally in the Player1/Player methods. so when the method ends the player will be deallocated. Keep the generated player as a class member so it won't be deallocated when the method exits

In your class add:

class YourClass
{
    let url1 = Bundle.main.bundleURL.appendingPathComponent("music1.mp3")
    let url2 = Bundle.main.bundleURL.appendingPathComponent("music2.mp3")

    @IBOutlet weak var yourButton: CustomButton!
    @IBOutlet weak var yourButton2: CustomButton! 

    fileprivate var player1: AVAudioPlayer? 
    fileprivate var player2: AVAudioPlayer?

    .
    .
    .

    func Player(url: URL) {
        do {
            try player1 = AVAudioPlayer(contentsOf:url)
            player1!.play()
            yourButton.isSelected = true
            player1!.delegate = self
        } catch {
            print(error)
        }
    }

Another thing.. you are using a delegate method audioPlayerDidFinishPlaying which is a delegate method of the AVAudioPlayer. however audioPlayerDidFinishPlaying2 is not so it is useless here. Since you have two players with one class as the delegate you will need to identify which player has finished and change the correct button.

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    if (player === player1) {
        yourButton.isSelected = false
    } else if (player === player2) {
        yourButton2.isSelected = false
    }
}

Upvotes: 2

Related Questions