Play a sound based on the button pressed on the IPhone/xcode - iphone

I'm trying to play a sound based on which button is pressed using AVAudioPlayer.
(This is not a soundboard or fart app.)
I have linked all buttons using this code in the header file:
#interface appViewController : UIViewController <AVAudioPlayerDelegate> {
AVAudioPlayer *player;
UIButton *C4;
UIButton *Bb4;
UIButton *B4;
UIButton *A4;
UIButton *Ab4;
UIButton *As4;
UIButton *G3;
UIButton *Gb3;
UIButton *Gs3;
UIButton *F3;
UIButton *Fs3;
UIButton *E3;
UIButton *Eb3;
UIButton *D3;
UIButton *Db3;
UIButton *Ds3;
UIButton *C3;
UIButton *Cs3;
}
#property (nonatomic, retain) AVAudioPlayer *player;
#property (nonatomic, retain) IBOutlet UIButton *C4;
#property (nonatomic, retain) IBOutlet UIButton *B4;
#property (nonatomic, retain) IBOutlet UIButton *Bb4;
#property (nonatomic, retain) IBOutlet UIButton *A4;
#property (nonatomic, retain) IBOutlet UIButton *Ab4;
#property (nonatomic, retain) IBOutlet UIButton *As4;
#property (nonatomic, retain) IBOutlet UIButton *G3;
#property (nonatomic, retain) IBOutlet UIButton *Gb3;
#property (nonatomic, retain) IBOutlet UIButton *Gs3;
#property (nonatomic, retain) IBOutlet UIButton *F3;
#property (nonatomic, retain) IBOutlet UIButton *Fs3;
#property (nonatomic, retain) IBOutlet UIButton *E3;
#property (nonatomic, retain) IBOutlet UIButton *Eb3;
#property (nonatomic, retain) IBOutlet UIButton *D3;
#property (nonatomic, retain) IBOutlet UIButton *Db3;
#property (nonatomic, retain) IBOutlet UIButton *Ds3;
#property (nonatomic, retain) IBOutlet UIButton *C3;
#property (nonatomic, retain) IBOutlet UIButton *Cs3;
- (IBAction) playNote;
#end
Buttons are all linked to the event "playNote" in interfaceBuilder and each note is linked to the proper referencing outlet according to note name.
All *.mp3 sound files are named after the UIButton name (IE- C3 == C3.mp3).
In my implementation file, I have this to play a only one note when the C3 button is pressed:
#import "sonicfitViewController.h"
#implementation appViewController
#synthesize C3, Cs3, D3, Ds3, Db3, E3, Eb3, F3, Fs3, G3, Gs3, A4, Ab4, As4, B4, Bb4, C4;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"3C" ofType:#"mp3"];
NSLog(#"path: %#", path);
NSURL *file = [[NSURL alloc] initFileURLWithPath:path];
AVAudioPlayer *p = [[AVAudioPlayer alloc]
initWithContentsOfURL:file error:nil];
[file release];
self.player = p;
[p release];
[player prepareToPlay];
[player setDelegate:self];
[super viewDidLoad];
}
- (IBAction) playNote {
[self.player play];
}
Now, with the above I have two issues:
First, the NSLog reports NULL and crashes when trying to play the file. I have added the mp3's to the resources folder and they have been copied and not just linked. They are not in an subfolder under the resources folder.
Secondly, how can I set it up so that when say button C3 is pressed, it plays C3.mp3 and F3 plays F3.mp3 without writing duplicate lines of code for each different button? playNote should be like
NSString *path = [[NSBundle mainBundle] pathForResource:nameOfButton ofType:#"mp3"];
instead of defining it specifically (#"C3").
Is there a better way of doing this and why does the *path report NULL and crash when I load the app?
I'm pretty sure it's something as simple as adding additional variable inputs to - (IBAction) playNote:buttonName and putting all the code to call AVAudioPlayer in the playNote function but I'm unsure of the code to do this.

Performing multiple actions with same selector is a common task. Just set a tag property for each button and use a NSArray of NSStrings to store file names. Your even need not create each button separately. See code sample for similar question problem with selector in iphone? answer.
Check if your files is realy copied to bundle. For example in simulator
log your bundle directory with NSLog(#"myBundle:%#",[[NSBundle mainBundle] bundlePath]);
and look at files.

Related

Releasing iVar IBOutlet vs Property IBOutlet

Can anyone verify my dealloc method is correct? Since my titleLabel and checkImageView are retained I am releasing them in dealloc. However, I am not releasing mainImageView, doneButton, and noteLabel, because they are not retained or alloced during the implementation.
#interface CheckMarkController : UIViewController <UIAlertViewDelegate> {
IBOutlet UIImageView *mainImageView;
IBOutlet UIButton *doneButton;
IBOutlet UILabel *noteLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *titleLabel;
#property (nonatomic, retain) IBOutlet UIImageView *checkImageView;
#property (nonatomic, retain) Event *event;
#property (nonatomic, retain) Workout *workout;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#end
- (void)dealloc {
//props
[titleLabel release];
[checkImageView release];
[event release];
[workout release];
[managedObjectContext release];
[super dealloc];
If you connect these three items via Interface Builder you DO need to release them. Outlets are retained by default. KVC (Key Value Coding) is used to set outlets. This means that loadFromNib will call setValue:withKey for each outlet you have set. This uses the #property and it's setter method, but if none are set (as is your case) it retains the object by default.

Load a view .xib in MainWindow.xib

It`s probably a very silly mistake, but I've spent over 4 days looking for a solution for this.
It is very simple, I´ve got my MainView.xib and a view called FirstViewController (h/m/xib).
In MainWindow.xib I add a UIViewController and change the class name to FirstViewController and set the Nib name also (altouhg I've tried both ways).
I guess it has to do something with outlets, but I can`t really tell, as I am a newbie developing for iOS, any help wil REALLY help a lot.
Im using XCode 3.2 and interface builder, with SDK 4.3
AppDelegate
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface iPadTerritorioV2AppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UIWindow *window;
IBOutlet UIViewController *navigationController;
NSString *devToken;
NSString *matricula;
NSString *campus;
NSMutableArray *materiasAlumno; //para CCM
NSMutableArray *busqDir; //para CCM
NSInteger agendaBadgeNumber;
NSInteger intramurosBadgeNumber;
NSInteger notificacionesBadgeNumber;
NSInteger mapaBadgeNumber;
NSMutableData *receivedData;
NSMutableDictionary *listData;
BOOL yaSeHizoElPrimerFetchBadges;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UIViewController *navigationController;
#property (nonatomic, retain) NSString *devToken;
#property (nonatomic, retain) NSString *matricula;
#property (nonatomic, retain) NSString *campus;
#property (nonatomic, retain) NSMutableArray *materiasAlumno;
#property (nonatomic, retain) NSMutableArray *busqDir;
#property NSInteger agendaBadgeNumber;
#property NSInteger intramurosBadgeNumber;
#property NSInteger notificacionesBadgeNumber;
#property NSInteger mapaBadgeNumber;
#property (nonatomic, retain) NSMutableData *receivedData;
#property (nonatomic, retain) NSMutableDictionary *listData;
#property BOOL yaSeHizoElPrimerFetchBadges;
- (void)fetchBadges;
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#import "Constants.h"
#import "StringDecoding.h"
#define kConnectionBadgeNotifications 0
#define kConnectionLogin 1
#define kConnectionDevToken 2
#define kCCMindex 0
#define kCSFindex 1
#define kMTYindex 2
#interface FirstViewController : UIViewController {
IBOutlet UISegmentedControl *segmentedCampus;
IBOutlet UITextField *usernameField;
IBOutlet UITextField *passwordField;
IBOutlet UISwitch *remembermeSwitch;
IBOutlet UIButton *loginButton;
UIActivityIndicatorView *loginIndicator;
NSMutableDictionary *listData;
NSMutableData *receivedData;
NSInteger connectionID;
}
#property (nonatomic, retain) UISegmentedControl *segmentedCampus;
#property (nonatomic, retain) UITextField *usernameField;
#property (nonatomic, retain) UITextField *passwordField;
#property (nonatomic, retain) UIActivityIndicatorView *loginIndicator;
#property (nonatomic, retain) UISwitch *remembermeSwitch;
#property (nonatomic, retain) UIButton *loginButton;
#property (nonatomic, retain) NSMutableDictionary *listData;
#property (nonatomic, retain) NSMutableData *receivedData;
#property NSInteger connectionID;
- (IBAction)handleNextClick:(id) sender;
- (IBAction)backgroundClick;
- (IBAction)login: (id) sender;
#end
It sounds like your FirstViewController isn't being retained - if it's not assigned to an outlet anywhere, nothing's retaining it and it'll just disappear. Add a property somewhere (your AppDelegate, perhaps, if that's all you've got) and connect it to the controller:
#property (nonatomic, retain) IBOutlet UIViewController *firstViewController;

Why doesn't IB see my IBAction?

I've been staring at this for way too long.
There's nothing fancy happening here, and I've done this dozens of times, yet Interface Builder steadfastly refuses to provide me an action target for -(IBAction)slideDirections. I'm at the point where I'm willing to post publicly and feel stupid. So let 'er rip.
Here's my .h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface PulseDetailController : UIViewController {
NSDictionary *pulse;
IBOutlet MKMapView *map;
IBOutlet UIWebView *directions;
IBOutlet UIView *directionsSlider;
BOOL directionsExtended;
IBOutlet UILabel *vendor;
IBOutlet UILabel *offer;
IBOutlet UILabel *offerText;
IBOutlet UILabel *hours;
IBOutlet UILabel *minutes;
IBOutlet UILabel *seconds;
IBOutlet UILabel *distance
}
#property (nonatomic, retain) NSDictionary *pulse;
#property (nonatomic, retain) MKMapView *map;
#property (nonatomic, retain) UIWebView *directions;
#property (nonatomic, retain) UIView *directionsSlider;
#property (nonatomic) BOOL directionsExtended;
#property (nonatomic, retain) UILabel *vendor;
#property (nonatomic, retain) UILabel *offer;
#property (nonatomic, retain) UILabel *offerText;
#property (nonatomic, retain) UILabel *hours;
#property (nonatomic, retain) UILabel *minutes;
#property (nonatomic, retain) UILabel *seconds;
#property (nonatomic, retain) UILabel *distance;
-(IBAction)slideDirections;
#end
Shouldn't the IBAction have a sender parameter?
Like:
-(IBAction)slideDirections:(id)sender;
Sometimes Interface Builder seems to get out of sync with classes in Xcode. Have you tried forcing interface builder to reread your PulseDetailController header file? (File -> Read Class Files... -> Select 'PulseDetailController.h'). This should force Interface Builder to see your new action.
Which objects are you trying to connect?
From your header, the logical choice would be UIView *directionsSlider
If you are ctrl dragging from directionsSlider to the "File's Owner" object, make sure that the Class in "File's Owner" is set to PulseDetailController.

iPhone UIImageView Array

So I'm declaring a NSMutableArray to hold 5 UIImageViews.
.h file:
#interface ImageDisplay : UIViewController {
IBOutlet UIImageView *img1;
IBOutlet UIImageView *img2;
IBOutlet UIImageView *img3;
IBOutlet UIImageView *img4;
IBOutlet UIImageView *img5;
NSMutableArray *imageHolderArray;
}
#property (nonatomic, retain) IBOutlet UIImageView *img1;
#property (nonatomic, retain) IBOutlet UIImageView *img2;
#property (nonatomic, retain) IBOutlet UIImageView *img3;
#property (nonatomic, retain) IBOutlet UIImageView *img4;
#property (nonatomic, retain) IBOutlet UIImageView *img5;
#property (nonatomic, retain) IBOutlet NSMutableArray *imageHolderArray;
#end
In the .m file:
//All objects are synthesized, just easier not to crowd the screen
- (void)viewDidLoad {
[super viewDidLoad];
imageHolderArray = [[NSMutableArray alloc] initWithObjects: img1,img2,img3,img4,img5,nil];
NSLog(#"imageHolderArray count: %i",[imageHolderArray count]); //Returns count of 1
}
So my question is, why is this happening? Why isn't it picking up all the objects in the Array? I'm not well versed in Objective-C programming so I'd appreciate it if someone could clue me in here. Thank you.
Because you didn't wire the IBOutlets to their views in Interface Builder. Looks like you probably wired img1, but didn't wire img2, so img2 is nil, which marks the end of your list of objects for -initWithObjects: even if later outlets are wired.

How can I store UIButtons in an array?

I have a method tied to four buttons. I want to create an array containing each button, and later retrieve and interact w/ a button from the array. The code I was tinkering with below. When I try to get a button from the array and send it a message, it goes kablooie.
Any thoughts on what I'm doing wrong?
Hack_DumpViewController.h
#import <UIKit/UIKit.h>
#interface Hack_DumpViewController : UIViewController {
IBOutlet UIButton *redButton;
IBOutlet UIButton *greenButton;
IBOutlet UIButton *blueButton;
IBOutlet UIButton *yellowButton;
NSArray *buttonMapping;
}
- (IBAction) changeToYo:(id)sender;
#property (nonatomic, retain) UIButton *redButton;
#property (nonatomic, retain) UIButton *greenButton;
#property (nonatomic, retain) UIButton *blueButton;
#property (nonatomic, retain) UIButton *yellowButton;
#property (nonatomic, retain) NSArray *buttonMapping;
#end
Hack_DumpViewController.m
#import "Hack_DumpViewController.h"
#implementation Hack_DumpViewController
#synthesize redButton;
#synthesize greenButton;
#synthesize yellowButton;
#synthesize blueButton;
#synthesize buttonMapping;
- (IBAction) changeToYo:(id)sender {
NSLog(#"changing numbers!");
for (UIButton *b in buttonMapping) {
[b setTitle:#"yo!"];
}
NSLog(#"changed to numbers!");
}
- (void)viewDidLoad {
buttonMapping = [[NSArray alloc] initWithObjects:greenButton, redButton, yellowButton, blueButton, nil];
}
[NSArray arrayWithObjects:...] returns an autoreleased array, so by the time you use it, it no longer exists and you end up messaging an invalid pointer. What you want is [[NSArray alloc] initWithObjects:...] (remembering to release it in your dealloc).
Why not tag the views in interface builder and then treat them like an array, much easier