Question

How can I play a sound by touching a UICollectionViewCell once, and stop the same sound by touching the same UICollectionViewCell again, using AVAudioPlayer?

My code plays the sound correctly, but it won't stop it when I press the cell, it just starts the loop from the beginning. My current code is the following:

// Sound
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {


// Loop
int loopOrNot;
BOOL playing = 0;

if ([loopArray containsObject:saveFavorite]) // YES
{
    loopOrNot = -1;


} else {

    loopOrNot = 0;

}
// Play soundeffects

if (playing==NO) {
    // Init audio with playback capability


    // Play sound even in silent mode
    [[AVAudioSession sharedInstance]
     setCategory: AVAudioSessionCategoryPlayback
     error: nil];

    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.wav", [[NSBundle mainBundle] resourcePath], [mainArray objectAtIndex:indexPath.row]]];

    NSError *error;
    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    audioPlayer.numberOfLoops = loopOrNot;

    if (audioPlayer == nil) {
        //  NSLog([error description]);
    }
    else {
        [audioPlayer play];
    }

    playing=YES;
}
else if(playing==YES){

[audioPlayer stop];


    playing=NO;
}
}
Was it helpful?

Solution

Here's a quick way to do it (using Swift 2.0 FYI). Define a counter as a global variable and set it to 0. When you press the button again, stop the audio and reset its start time. Hope this helps.

func setupAudioPlayerWithFile(file:NSString, type:NSString) -> AVAudioPlayer  {
    let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
    let url = NSURL.fileURLWithPath(path!)
    var audioPlayer:AVAudioPlayer?

    do {
        try audioPlayer = AVAudioPlayer(contentsOfURL: url)
    } catch {
        print("NO AUDIO PLAYER")
    }

    return audioPlayer!
}


@IBAction func buttonTap(sender: AnyObject) {
    if (counter%2==0)
    {
    backMusic = setupAudioPlayerWithFile("Etudes", type: "mp3")
    backMusic.play()
    }
    else
    {
        backMusic.stop()
        backMusic.currentTime = 0.0
    }
    counter++

OTHER TIPS

On the beginning on your method you set up:

BOOL playing = 0;

and your first if statement:

if (playing==NO) {

always is true.

Add to the beginning of your method, before:

BOOL playing = 0;

this:

if(playing==YES){
   [audioPlayer stop];
    playing=NO;
    return
}

And after that add the code which set up the player. In this situation if the player is playing it stop it and return from the function and if it's not playing it create player and start playing.

Also replace this line:

BOOL playing = 0;

with

playing = 0;

And declare this as a ivar

@implementation YourClassName
{
    BOOL playing;
}

That's because your playing variable is local to that function, and it's value is not preserved across calls. It is being initialized as NO every time the function is called. Move that variable to your class declaration.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top