Best ways to play simple sound effect in iOS

I'm finding a number of conflicting data about playing sounds in iOS. What is a recommended way to play just a simple "ping" sound bite every time the user touches the screen?


Solution 1:

I use this:

Header file:

#import <AudioToolbox/AudioServices.h>

@interface SoundEffect : NSObject
{
    SystemSoundID soundID;
}

- (id)initWithSoundNamed:(NSString *)filename;
- (void)play;

@end

Source file:

#import "SoundEffect.h"

@implementation SoundEffect

- (id)initWithSoundNamed:(NSString *)filename
{
    if ((self = [super init]))
    {
        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:filename withExtension:nil];
        if (fileURL != nil)
        {
            SystemSoundID theSoundID;
            OSStatus error = AudioServicesCreateSystemSoundID((__bridge CFURLRef)fileURL, &theSoundID);
            if (error == kAudioServicesNoError)
                soundID = theSoundID;
        }
    }
    return self;
}

- (void)dealloc
{
    AudioServicesDisposeSystemSoundID(soundID);
}

- (void)play
{
    AudioServicesPlaySystemSound(soundID);
}

@end

You will need to create an instance of SoundEffect and direct call the method play on it.

Solution 2:

This is the best way of playing a simple sound in iOS (no more than 30 seconds):

//Retrieve audio file
NSString *path  = [[NSBundle mainBundle] pathForResource:@"soundeffect" ofType:@"m4a"];
NSURL *pathURL = [NSURL fileURLWithPath : path];

SystemSoundID audioEffect;
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);

// call the following function when the sound is no longer used
// (must be done AFTER the sound is done playing)
AudioServicesDisposeSystemSoundID(audioEffect);

Solution 3:

(Small amendment to the correct answer to take care of the disposing of the audio)

NSString *path  = [[NSBundle mainBundle] pathForResource:@"soundeffect" ofType:@"m4a"];
NSURL *pathURL = [NSURL fileURLWithPath : path];

SystemSoundID audioEffect;
AudioServicesCreateSystemSoundID((__bridge CFURLRef) pathURL, &audioEffect);
AudioServicesPlaySystemSound(audioEffect);
// Using GCD, we can use a block to dispose of the audio effect without using a NSTimer or something else to figure out when it'll be finished playing.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    AudioServicesDisposeSystemSoundID(audioEffect);
});