Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift checking if AVAudioPlayer is playing crash

I am making a soundboard with Swift. It works great but I am trying to impement a check whether AVAudioPlayer instance is playing, and if yes to stop it. The sounds are listed on a tableview which gets the data from an array in which I store my Sound class (which has 2 variables, title and url of sound).

I have my AVAudioPlayer and AVAudioSession as well as my sounds array on my ViewController Class:

 var session = AVAudioSession.sharedInstance()
 var audioPlayer = AVAudioPlayer()
 var sounds: [Sound] = []

and I implement the audio playing when the app user selects a row like that:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            if audioPlayer.playing {

                audioPlayer.stop()
            } else {
            var sound = self.sounds[indexPath.row]

            var baseString : String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as String
            var pathComponents = [baseString, sound.url]
            var audioNSURL = NSURL.fileURLWithPathComponents(pathComponents)

            self.audioPlayer = AVAudioPlayer(contentsOfURL: audioNSURL, error: nil)
            self.audioPlayer.play()

        }
            tableView.deselectRowAtIndexPath(indexPath, animated: true)

    }

But when I tap the row the app is crashing and all I am getting is "(lldb)"

Do you have any idea what is happening? Or am I doing this completely wrong?

Thank you in advance

like image 395
WizMeister Avatar asked Nov 23 '14 12:11

WizMeister


1 Answers

I figured it out, so I share with the community:

I also had to declare the sound NSURL property on my ViewController Class:

var session = AVAudioSession.sharedInstance()
var audioPlayer = AVAudioPlayer()
var audioNSURL = NSURL()

and also to prepare my audioPlayer on the ViewDidLoad function: (I had to use a sample sound in order to initialize the AVAudioPlayer)

let samplePath = NSBundle.mainBundle().pathForResource("sample", ofType: "mp4")
audioNSURL = NSURL.fileURLWithPath(samplePath!)!
audioPlayer = AVAudioPlayer(contentsOfURL: audioNSURL, error: nil)
audioPlayer.prepareToPlay()

then, on the didSelectRowAtIndexPath method, I check whether the AVAudioPlayer instance is playing and also if it's playing the sound reflected by the cell that was tapped. If yes, stop the audioPlayer, if not then play the other sound (the audioPlayer stops and plays the other sound)

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        var sound = self.sounds[indexPath.row]
        var baseString : String = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0] as String
        var pathComponents = [baseString, sound.url]

        var rowSoundURL = NSURL.fileURLWithPathComponents(pathComponents)!


        if audioPlayer.playing && rowSoundURL == audioNSURL {

            audioPlayer.stop()

        } else {

            audioNSURL = rowSoundURL

            self.audioPlayer = AVAudioPlayer(contentsOfURL: audioNSURL, error: nil)
            self.audioPlayer.play()

        }

            tableView.deselectRowAtIndexPath(indexPath, animated: true)

    }

Be aware, that, if you also record sounds on your app, you have to set the session category as AVAUdioSessionCategoryPlayback or the sound will be heard through the small speaker of the device. So, in viewWillAppear function:

session.setCategory(AVAudioSessionCategoryPlayback, error: nil)
like image 118
WizMeister Avatar answered Sep 28 '22 06:09

WizMeister