Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Adding a sound in the Crystal Ball app

NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"crystal_ball" ofType:@"mp3"];
NSURL *soundURL = [NSURL fileURLWithPath:soundPath];

AudioServicesCreateSystemSoundID(CFBridgingRetain(soundURL), &soundEffect);

Please can someone break down this code for me? I am struggling to understand why an NSString variable is created, then a URL and finally the AudioServices C code.

2 Answers

Michael Hulet
Michael Hulet
47,909 Points

So what's happening is this line figures out where the sound file you want to play is located in the iPhone's filesystem:

NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"crystal_ball" ofType:@"mp3"];

Then, this line converts the NSString named soundPath to a usable URL to where the file is located in the iPhone filesystem:

NSURL *soundURL = [NSURL fileURLWithPath:soundPath];

This must be done because the call on the next line only accepts URLs, and not strings. Finally, this C function creates a SystemSoundID for the file that you want to play, so you can play it later with AudioServicesPlaySystemSound(soundEffect);:

AudioServicesCreateSystemSoundID(CFBridgingRetain(soundURL), &soundEffect);

Admittedly, that is a little complex, especially the last line. To break down the last line, AudioServicesCreateSystemSoundID(); is called to create a SystemSoundID for the file you passed in. This C function takes 2 parameters: a URL, and the memory address of the variable that you want the sound assigned to. Since it is a purely C function, the URL must be converted into a format that can be used by C, which NSURL is not. Therefore, CFBridgingRetain() is called on the NSURL named soundURL to convert it to a format usable by C. What that function returns is then passed into AudioServicesCreateSystemSoundID(); as its first parameter. The second parameter that is passed into it is &soundEffect, which is the memory address (as denoted by the "&") of the variable named soundEffect, which was declared at the top of the @implementation, like this:

@implementation THViewController{
    SystemSoundID soundEffect;
}

The sound ID (which can be thought of as the sound itself) is assigned to that variable, so it can later be played like this:

AudioServicesPlaySystemSound(soundEffect);

Michael, thank you for taking the time to give me a detailed explanation. That has really helped me understand once broken down into a more newbie friendly format!