AVAudioPlayer wont play sound when called in other swift file

1k views Asked by At

I have two swift files - my ViewController:UIViewController and AudioPlayer:AVAudioPlayer.

My AudioPlayer file has this function

func seaGullSound() {

    var tmp = AVAudioPlayer()

    var seaGullSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Gulls", ofType: "mp3")!)

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    tmp = AVAudioPlayer(contentsOfURL: seaGullSound, error: &error)
    tmp.prepareToPlay()
    tmp.play()

    println("This function got called!")
}

I'm trying to call that function in my ViewController thru tapping a button, using this code:

@IBAction func playSound(sender: AnyObject) {
    var audio = AudioPlayer()
    audio.seaGullSound()
}

The sound is not played when I click the button. However, the print statement works. I can get the audio to play if I move seaGullSound() to the ViewController file, so I know the mp3 does work. I haven't moved the audio to ViewController because I want to develop the habit of not crowding all my code into one file. Thanks in advance for the help.

edit:

class HighScore: UIViewController {

var audioInitializer = AudioPlayer()

func updateHighScore(score:Int) -> String {
    NSUserDefaults.standardUserDefaults().integerForKey("highscore")

    //Check if score is higher than NSUserDefaults stored value and change NSUserDefaults stored value if it's true
    if score > NSUserDefaults.standardUserDefaults().integerForKey("highscore") {
        //call applause sound
        audioInitializer.applauseSound()
        //set score
        NSUserDefaults.standardUserDefaults().setInteger(score, forKey: "highscore")
        NSUserDefaults.standardUserDefaults().synchronize()
    }
    NSUserDefaults.standardUserDefaults().integerForKey("highscore")

    //use below line to reset high score for testing
    //NSUserDefaults.standardUserDefaults().removeObjectForKey("highscore")

    return String(NSUserDefaults.standardUserDefaults().integerForKey("highscore"))
}}

here is the file with the sounds:

class AudioPlayer: AVAudioPlayer {

var soundMaster = AVAudioPlayer()

func tappingSound() {

    var tapSoundURL = NSBundle.mainBundle().URLForResource("tapSound", withExtension: "mp3")

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    soundMaster = AVAudioPlayer(contentsOfURL: tapSoundURL, error: &error)
    soundMaster.prepareToPlay()
    soundMaster.play()
}

//need to call in highscore.swift
func applauseSound() {
    var tapSoundURL = NSBundle.mainBundle().URLForResource("applause", withExtension: "mp3")

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    soundMaster = AVAudioPlayer(contentsOfURL: tapSoundURL, error: &error)
    soundMaster.prepareToPlay()
    soundMaster.play()
    println("did this get called?")
}}
1

There are 1 answers

12
Leo Dabus On BEST ANSWER

You just have move the declaration of your tmp AVAudioPlayer out of your method. Declare it as class variable.

You should also use URLForResource instead of pathForResource:

let seaGullSoundURL = NSBundle.mainBundle().URLForResource("Gulls", withExtension:  "mp3")!

Try like this:

import UIKit
import AVFoundation
class HighScore: UIViewController {
    var audioPlayer = AVAudioPlayer()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    func updateHighScore(score:Int) -> String {
        //Check if score is higher than NSUserDefaults stored value and change NSUserDefaults stored value if it's true
        if score > NSUserDefaults().integerForKey("highscore") {
            //call applause sound
            playAudio("applause")
            //set score
            NSUserDefaults().setInteger(score, forKey: "highscore")
        }
        //use below line to reset high score for testing
        //NSUserDefaults.standardUserDefaults().removeObjectForKey("highscore")
        return NSUserDefaults().integerForKey("highscore").description
    }
    func playAudio(audioName: String ) {
        var error:NSError?
        if let audioURL = NSBundle.mainBundle().URLForResource(audioName, withExtension: "mp3") {
            audioPlayer = AVAudioPlayer(contentsOfURL: audioURL, error: &error)
            audioPlayer.prepareToPlay()
            audioPlayer.play()
        } else if let error = error {
            println(error.description)
        }
    }
    @IBAction func playSound(sender: UIButton) {
        playAudio("Gulls")
    }
}