Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

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,842 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!