I am incredibly new to xcode and im making an app for a school project. I am working on a background music code to play/pause on the same button (found the code but modified it some). I've been able to clear up the other errors but I don't know what to do about this... expected identifier or "("
#implementation settingscontroller2
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;}
{ //expected Identifier or "("
if (button.selected){
// Play
NSString *path = [[NSBundle mainBundle] pathForResource:#"app" ofType:#"mp3"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.numberOfLoops = -1;
[theAudio play];
}
else (!button.selected){
// Pause
[theAudio pause];
return.nil
}
}
once check this one,
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;
if (button.selected){
// Play
NSString *path = [[NSBundle mainBundle] pathForResource:#"app" ofType:#"mp3"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
theAudio.numberOfLoops = -1;
[theAudio play];
}
else if(!button.selected){//here also one problem in your code.
// Pause
[theAudio pause];
//return.nil
}
}
In your line
button.selected = !button.selected;}
The "}" is too much as the following "{".
-(void) btnAction:(UIButton*)button{
button.selected = !button.selected;}
{ //expected Identifier or "("
You've got two method bodies here. It looks like you should probably remove the first } and the next {, and maybe reformat a bit, so that you have:
-(void) btnAction:(UIButton*)button
{
button.selected = !button.selected;
if (button.selected){
Try to replace the second last line with return;
try to remove the } at the end of
button.selected = !button.selected;
and the line that gives you error.
Related
In tableview footer i have a play button to play the music, as the music starts tableview scrolls automatically according to the audio played but if the user tap on particular cell, the content in the particular cell is playing and stops but i want to continue the music from where the use taps to the end. Below is the code. Please help.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int ref =(int) indexPath.row;
NSString *filePath = [soundArray objectAtIndex:ref];
NSString *Path = [[NSBundle mainBundle] pathForResource:filePath ofType:#"mp3"];
NSURL *musicFile = [NSURL fileURLWithPath:Path];
myAudioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:musicFile error:nil];
if (playing == YES) {
[playButton setBackgroundImage:[UIImage imageNamed:#"pause_White.png"] forState:UIControlStateNormal];
[myAudioPlayer play];
// playing = NO;
}
if (playing == NO) {
// [playButton setBackgroundImage:[UIImage imageNamed:#"play_white.png"] forState:UIControlStateNormal];
}
}
SoundArray contains trimmed music. How to continue the song ? Help much appreciated.
Here is my code as per my concept. You may have to manage it more as its just a sample
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
isMainMusic = NO;
// Construct URL to sound file
NSString *path = [NSString stringWithFormat:#"%#/1.mp3", [[NSBundle mainBundle] resourcePath]];
mainMusicUrl = [NSURL fileURLWithPath:path];
NSString *path1 = [NSString stringWithFormat:#"%#/2.mp3", [[NSBundle mainBundle] resourcePath]];
secondMusicUrl = [NSURL fileURLWithPath:path1];
}
-(void)playSecondaryMusic
{
if ([playMainMusic isPlaying]) {
[playMainMusic pause];
}
if (playSecondaryMusic) {
playSecondaryMusic.delegate = nil;
playSecondaryMusic = nil;
}
isMainMusic = NO;
playSecondaryMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:secondMusicUrl error:nil];
playSecondaryMusic.delegate = self;
[playSecondaryMusic play];
}
- (IBAction)playMainMusic:(UIButton *)sender {
if (playMainMusic) {
playMainMusic.delegate = nil;
playMainMusic = nil;
}
isMainMusic = YES;
playMainMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:mainMusicUrl error:nil];
playMainMusic.delegate = self;
[playMainMusic play];
}
//Delegate method
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
if (isMainMusic)
{
NSLog(#"Main music");
}
else
{
NSLog(#"Second music");
[playMainMusic play];
isMainMusic = YES;
}
}
So it has been brought to my attention that I should optimise the way I load and use sounds in a small game that I am developing for iOS.
I load a "boing" sound and play it every time I tap the screen, making the sprite jump (like mario).
I want to be able to play the sound every time, even if the sound is already playing from the previous jump...
Below are the 2 ways I'm currently using:
1st implementation:
//load the music from file
-(void)LoadMusic{
jumpSound = [[NSBundle mainBundle] pathForResource:#"boing" ofType:#"mp3"];
}
//call in viewDidLoad
- (void)viewDidLoad{
[self LoadMusic];
...
[super viewDidLoad];
}
//play sound when called
-(void)playSound{
jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
[jumpAffect play];
}
//tap/touch to jump (& play sound)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event{
[self playSound];
jumpUp = 16;
}
2nd implementation:, this is similar except I load the same file 5 times, and loop through to the next one (so the same sound affect can be called even if it's already in previous session).
int soundStage = 1;
//load the music from file
-(void)LoadMusic{
jumpSound = [[NSBundle mainBundle] pathForResource:#"Boing" ofType:#"mp3"];
jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect.delegate = self;
jumpAffect2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect2.delegate = self;
jumpAffect3 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect3.delegate = self;
jumpAffect4 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect4.delegate = self;
jumpAffect5 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
jumpAffect5.delegate = self;
}
//call in viewDidLoad
- (void)viewDidLoad{
[self LoadMusic];
...
[super viewDidLoad];
}
//tap/touch to jump (& play sound)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event{
jumpUp = 16;
if(soundStage == 1){
[jumpAffect play];
soundStage = 2;
}
else if(soundStage == 2){
[jumpAffect2 play];
soundStage = 3;
}
else if(soundStage == 3){
[jumpAffect3 play];
soundStage = 4;
}
else if(soundStage == 4){
[jumpAffect4 play];
soundStage = 5;
}
else if(soundStage == 5){
[jumpAffect5 play];
soundStage = 1;
}
I'm wondering which why is the better way? I'm hoping to avoid memory leaks and just optimise it by being able to continuously have the same sound play when the screen is tapped. Thanks.
AVAudioPlayer plays multiple sounds simultaneously, one sound per audio player. So better is to load/play your quick sound inside the touchesBegan method without keeping the reference:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event
{
NSString *jumpSound = [[NSBundle mainBundle] pathForResource:#"boing" ofType:#"mp3"];
AVAudioPlayer *jumpAffect = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:jumpSound] error:NULL];
[jumpAffect prepareToPlay];
[jumpAffect play];
jumpUp = 16;
}
I was trying to play a song in iOS, but it gives me an error message.
HEADER FILE .h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#interface PRPViewController : UIViewController{
AVAudioPlayer *audioPlayer;
IBOutlet UIButton *start;
}
-(IBAction)play;
#end
IMPLEMENTATION FILE .m
NSURL *url = [NSURL fileURLWithPath:
[NSString stringWithFormat:#"%#/bobmarley.mp3",
[[NSBundle mainBundle] resourcePath]]];
NSError *error;
audioPlayer = [[AVAudioPlayer alloc] initWithContentsofURL:url error:&error];
audioPlayer.numberOfLoops = 0;
[audioPlayer play];
but it says
No visible #interface for AVAudioPlayer declares the selector 'initWithContentsofUrl:error:'
What should I do?
You should capitalize the "O" in Of. In Objective-C, spelling counts, including capitalization. initWithContentsofURL and initWithContentsOfURL are two different things.
(By the way, this is a very good reason for using autocompletion as much as possible. The autocompletion mechanism knows much better than you do how to spell the names of the declared methods!)
You should check if the file is available on your system with the method initWithContentsOfURL, yours is written wrong. Otherwise the app can crash. I created a class which handles everything for me:
#implementation AudioPlayer{
AVAudioPlayer *_sound;
NSURL *_soundURL;
NSString *_receivedValue;
float _volumeSpecific;
}
- (id)initWithAudioFile:(NSString *)fileName andExtension:(NSString *)extension{
self = [super init];
if( self ){
_receivedValue = fileName;
_soundURL = [NSURL fileURLWithPath:
[[NSBundle mainBundle] pathForResource:fileName
ofType:extension]];
if([[NSFileManager defaultManager] fileExistsAtPath:[_soundURL path]]){
_sound = [[AVAudioPlayer alloc] initWithContentsOfURL:_soundURL
error:nil];
}
}
return self;
}
- (void)playEndless{
if( [[NSUserDefaults standardUserDefaults] boolForKey:kSound] ){
_sound.numberOfLoops = -1;
[_sound play];
}
}
- (void)setVolume:(float)myVolume{
_volumeSpecific = myVolume;
[_sound setVolume:myVolume];
}
- (void)play{
if( _sound == nil ){
NSLog(#"No AudioPlayer available %#", self);
}
if( [[NSUserDefaults standardUserDefaults] boolForKey:kSound] ){
if( _volumeSpecific ){
[_sound setVolume:_volumeSpecific];
}
[_sound play];
}
}
- (NSString *)description{
return [NSString stringWithFormat:#"Received: %#, Player: %#, URL: %#",
_receivedValue, _sound, _soundURL];
}
//Action to play Audio//
-(IBAction)playAudio:(id)sender {
[self.loopPlayer play];
}
//Action to stop Audio//
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer.isPlaying) {
[self.loopPlayer stop];
self.loopPlayer.currentTime = 0;
self.loopPlayer.numberOfLoops = -1;
[self.loopPlayer prepareToPlay];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Code that gets audio file "trap synth"//
NSURL* audioFileURL = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
}
This is the code i'm using with one button to play the sound when the button is tapped and stop the sound when the button is released. How would I go about adding more sounds to more buttons? I want to have more buttons that play and stop different sounds just like this.
property (nonatomic, strong) AVAudioPlayer *loopPlayer;
This code is also in my ViewController.h file
Ok although the answer provided by Miro is on the write track the code example given has issues.
Should be this in viewDidLoad -
- (void)viewDidLoad {
[super viewDidLoad];
NSURL* audioFileURL1 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL1 error:nil];
NSURL* audioFileURL2 = [[NSBundle mainBundle] URLForResource:#"other_audio_file" withExtension:#"wav"];
self.loopPlayer2 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL2 error:nil];
}
also stopAudio: method should be this
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer1.isPlaying && (sender.tag == 1)) {
[self.loopPlayer1 stop];
self.loopPlayer1.currentTime = 0;
self.loopPlayer1.numberOfLoops = -1;
[self.loopPlayer1 prepareToPlay];
}
if (self.loopPlayer2.isPlaying && (sender.tag == 2)) {
[self.loopPlayer2 stop];
self.loopPlayer2.currentTime = 0;
self.loopPlayer2.numberOfLoops = -1;
[self.loopPlayer2 prepareToPlay];
}
}
And finally for playAudio:
-(IBAction)playAudio:(id)sender {
if([sender tag] == 1){
[self.loopPlayer1 play];
}
if([sender tag] == 2){
[self.loopPlayer2 play];
}
}
If you want to play different sounds at the same time you should look into creating separate AVAudioPlayers - if you create a different one for each sound, then you can easily control (play/stop) each of them separately with a specific button.
On the simplest level, you could do something like this, which allows you to use the same button handlers for all your audio. The playAudio checks the tag of the Play button you press (be sure to set the tag value in IB, to 1,2,etc). There really only need be one Stop button.
You could enhance this in many ways, like attempting to reuse the AVAudioPlayer somehow, and loading the audio on the fly instead of all at the beginning. Or storing your audio file info in an array, creating an array of AVAudioPlayers for management, etc. But this is a start.
-(IBAction)playAudio:(id)sender {
// first, stop any already playing audio
[self stopAudio:sender];
if([sender tag] == 1){
[self.loopPlayer1 play];
} else if([sender tag] == 2){
[self.loopPlayer2 play];
}
}
-(IBAction)stopAudio:(id)sender {
if (self.loopPlayer1.isPlaying) {
[self.loopPlayer1 stop];
self.loopPlayer1.currentTime = 0;
self.loopPlayer1.numberOfLoops = -1;
[self.loopPlayer1 prepareToPlay];
} else if (self.loopPlayer2.isPlaying) {
[self.loopPlayer2 stop];
self.loopPlayer2.currentTime = 0;
self.loopPlayer2.numberOfLoops = -1;
[self.loopPlayer2 prepareToPlay];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
NSURL* audioFileURL1 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer1 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
NSURL* audioFileURL2 = [[NSBundle mainBundle] URLForResource:#"trapsynth" withExtension:#"wav"];
self.loopPlayer2 = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL error:nil];
}
AND, in the .h file;
property (nonatomic, strong) AVAudioPlayer *loopPlayer1;
property (nonatomic, strong) AVAudioPlayer *loopPlayer2;
I have a soundboard app that plays sound and is supposed to play music and if you click the button then it pauses but it doesn't pause it only stops the music.
And once the music finishes the button stays selected.
My code is;
- (IBAction)aint:(id)sender {
UIButton *aint = (UIButton *)sender;
aint.selected = !aint.selected;
if(aint.selected)
{
// Play
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"mp3"];
theAudio2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path2] error:NULL];
theAudio2.delegate = self;
theAudio2.numberOfLoops = 0;
[theAudio2 play];
[[NSUserDefaults standardUserDefaults] setObject:#"-" forKey:#"music"];
}
else
{
// Pause
[theAudio2 pause];
}
}
And I have theAudio2 and AVAudioPlayer declared.
Try this it will work as expected -
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path2 = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"mp3"];
theAudio2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path2] error:NULL];
theAudio2.delegate = self;
theAudio2.numberOfLoops = 0;
}
- (IBAction)aint:(id)sender
{
UIButton *aint = (UIButton *)sender;
aint.selected = !aint.selected;
if(aint.selected)
{
// Play
[theAudio2 play];
[[NSUserDefaults standardUserDefaults] setObject:#"-" forKey:#"music"];
}
else
{
// Pause
[theAudio2 pause];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
playerBtn.selected = NO;
}