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! While you're at it, check out some resources Treehouse students have shared here.

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

Playing Audio With a button

Hi! In XCode I am trying to get a button that plays a click sound when pressed and hides and shows objects. My first attempt is here. It gets no errors but no audio plays when I click the button in the IOS 6.1 simulator.

-(IBAction)press {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 1;
tutorialbtn.hidden = 1;
optionsbtn.hidden = 1;
trainingbtn.hidden = 1;
back.hidden = 0;
cruzia.text = @"Play";
textarea.text = @"Hello! You are playing the game of Cruzia!";
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults stringForKey:kMusic])  {
        CFBundleRef mainBundle = CFBundleGetMainBundle();
        CFURLRef soundFileURLRef;
        soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click",                        CFSTR ("wav"), NULL);
        UInt32 soundID;
        AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
        AudioServicesPlaySystemSound(soundID); }

}

I tried again today with this code and errors this time:

- (IBAction) click {
if(clicked == 0) {
    clicked = 1;
    NSURL *url = [NSUrl fileURLWithPath:[NSSTring stringWithFormat:@"%@/Electronic Click.wav", [[NSBundle mainBundle resourcePath]]];
                  NSError *error;
                  audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfUrl:url error:&error];
                  audioPlayer.numberOfLoops = 0;
    }
}

Here is my complete ViewController.m:

#import "CIAViewController.h"

@interface CIAViewController()


@end

@implementation CIAViewController




-(IBAction)press {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 1;
tutorialbtn.hidden = 1;
optionsbtn.hidden = 1;
trainingbtn.hidden = 1;
back.hidden = 0;
cruzia.text = @"Play";
textarea.text = @"Hello! You are playing the game of Cruzia!";

    // declare defaults it is not declared elsewhere within your view controller
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // The stringForKey method returns a String and not a Boolean value
    // However, if you just want to check if a value exists then it is implied you are checking for existence
    // If there is no value then it will return nil and statement will fail
    // You had "== YES" outside of the parenthesis which is an illegal statement
    if ([defaults stringForKey:kMusic])  {
        CFBundleRef mainBundle = CFBundleGetMainBundle();
        CFURLRef soundFileURLRef;
        soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click",                     CFSTR ("wav"), NULL);
        UInt32 soundID;
        AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
        AudioServicesPlaySystemSound(soundID); }

}


-(IBAction)press2 {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 1;
tutorialbtn.hidden = 1;
optionsbtn.hidden = 1;
trainingbtn.hidden = 1;
back.hidden = 0;
cruzia.text = @"Tutorial";
textarea.text = @"Welcome! You are watching the Cruzia tutorial!";
// declare defaults it is not declared elsewhere within your view controller
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

// The stringForKey method returns a String and not a Boolean value
// However, if you just want to check if a value exists then it is implied you are checking for existence
// If there is no value then it will return nil and statement will fail
// You had "== YES" outside of the parenthesis which is an illegal statement
if ([defaults stringForKey:kMusic])  {
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef soundFileURLRef;
    soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click",                     CFSTR ("wav"), NULL);
    UInt32 soundID;
    AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
    AudioServicesPlaySystemSound(soundID); }
}

-(IBAction)press3:(id)sender {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 1;
tutorialbtn.hidden = 1;
optionsbtn.hidden = 1;
trainingbtn.hidden = 1;
back.hidden = 0;
cruzia.text = @"Options";
textarea.text = @"Hello! You have clicked Options. Sadly, you need to open Settngs and go to the Cruzia area to get most of the options of the game.";
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click", CFSTR ("wav"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}

-(IBAction)press4 {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 1;
tutorialbtn.hidden = 1;
optionsbtn.hidden = 1;
trainingbtn.hidden = 1;
back.hidden = 0;
cruzia.text = @"Training";
textarea.text = @"This is the training area. You can improve your Cruzia skills here!";
// declare defaults it is not declared elsewhere within your view controller
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

// The stringForKey method returns a String and not a Boolean value
// However, if you just want to check if a value exists then it is implied you are checking for existence
// If there is no value then it will return nil and statement will fail
// You had "== YES" outside of the parenthesis which is an illegal statement
if ([defaults stringForKey:kMusic])  {
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef soundFileURLRef;
    soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click",                     CFSTR ("wav"), NULL);
    UInt32 soundID;
    AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
    AudioServicesPlaySystemSound(soundID); }
}

-(IBAction)press5 {
cruzia.hidden = 0;
textarea.hidden = 0;
playbtn.hidden = 0;
tutorialbtn.hidden = 0;
optionsbtn.hidden = 0;
trainingbtn.hidden = 0;
back.hidden = 1;
cruzia.text = @"Cruzia";
textarea.text = @"";
// declare defaults it is not declared elsewhere within your view controller
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

// The stringForKey method returns a String and not a Boolean value
// However, if you just want to check if a value exists then it is implied you are checking for existence
// If there is no value then it will return nil and statement will fail
// You had "== YES" outside of the parenthesis which is an illegal statement
if ([defaults stringForKey:kMusic])  {
    CFBundleRef mainBundle = CFBundleGetMainBundle();

CFURLRef soundFileURLRef; soundFileURLRef =CFBundleCopyResourceURL(mainBundle, (CFStringRef) @"click", CFSTR ("wav"), NULL); UInt32 soundID; AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID); AudioServicesPlaySystemSound(soundID); } } }

- (void)viewDidLoad
{
textarea.hidden = 1;
playbtn.hidden = 0;
tutorialbtn.hidden = 0;
optionsbtn.hidden = 0;
trainingbtn.hidden = 0;
back.hidden = 1;
cruzia.text = @"Cruzia";
[super viewDidLoad];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSettings:)
                                            name:
 NSUserDefaultsDidChangeNotification object:nil];

 [self setupDefaults];
 }

- (void)viewDidUnload
{

[super viewDidUnload];

[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidFinishLaunchingNotification object:nil];
}

-(void) setupDefults {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];


NSString *violenceValue = [defaults stringForKey:kViolenceMode];

if ( violenceValue == nil ) {
    NSString *pathStr = [[NSBundle mainBundle] bundlePath];
    NSString *settingsBundlePath = [pathStr stringByAppendingPathComponent:@"Settings.bundle"];
    NSString *finalPath = [settingsBundlePath stringByAppendingPathComponent:@"Root.plist"];

    NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:finalPath];
    NSArray *prefSpecifierArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];


    NSString *isMusicOn, *isSoundOn;

    NSDictionary *prefItem;

    for (prefItem in prefSpecifierArray) {
        NSString *keyValue = [prefItem objectForKey:@"Key"];
        id defultValue = [prefItem objectForKey:@"DefultValue"];

        if ([keyValue isEqualToString:kSound])
        {
            isSoundOn = defultValue;
        }
        else if ([keyValue isEqualToString:kMusic])
        {
            isMusicOn = defultValue;
        }

        NSDictionary *appDefults = [NSDictionary dictionaryWithObjectsAndKeys:                                  isSoundOn, kSound, isMusicOn, kMusic, nil];

        [defaults registerDefaults:appDefults];
        [defaults synchronize];

    }

}

}



@end

And here is my ViewController.h:

#import <UIKit/UIKit.h>

#define kViolenceMode @"violence_identifier"
#define kSound @"isSoundOn"
#define kMusic @"isMusicOn"
#define kPushNotifications @"isPushNotifyOn"

@interface CIAViewController : UIViewController {

IBOutlet UILabel *cruzia;
IBOutlet UILabel *textarea;
IBOutlet UIButton *playbtn;
IBOutlet UIButton *tutorialbtn;
IBOutlet UIButton *optionsbtn;
IBOutlet UIButton *trainingbtn;
IBOutlet UIButton *back;
}

- (void) setupDefaults;

-(IBAction)press;
-(IBAction)press2; 
-(IBAction)press3;
-(IBAction)press4;
-(IBAction)press5;
@end

When I run my app, I used to get a sigabart error on this line:

[self setupDefaults];

My app now dosn't make it to that line. The build fails and I get three warnings: //first warning @implementation CIAViewController //incomplete implementation

//second warning
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
//Implicit declaration of function 'AudioServicesCreateSystemSoundID' is invalid on C99

//third warning
AudioServicesPlaySystemSound(soundID); }
//Implicit declaration of function 'AudioServicesPlaySystemSound' is invalid on C99

Anyone know a way of fixing this? Or a way of getting the buttons to work? Thanks -Raph

Hi I just realised that I spelt defaults wrong every time so I fixed that. I reckon the music will work now but what about these lines of code:

 AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
        AudioServicesPlaySystemSound(soundID); }

They still get these errors: implicit declaration of function '(function name)' is invalid on C99

And I also still get the Incomplete implementation error. I am going to start a new post for that and I'll give you the link in a second.

EDIT: Here is the link! https://teamtreehouse.com/forum/implicit-declaration-of-function-is-invalid-on-c99?tag=ios

1 Answer

Thanks I'll have a look at them now! Also do you know any way of fixing the three warnings?