iOS SDK : playing music on the background and swit

2020-01-29 10:00发布

问题:

I am trying to play music in my application. The music works fine but after switching viewControllers and returning to the main menu, my music plays again! It means several identical sounds play together! How can I solve this? Here is my code :

- (void)viewDidLoad {

    NSString *music = [[NSBundle mainBundle] pathForResource:@"1music" ofType:@"mp3"];
    myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:music] error:NULL];
    myMusic.delegate = self;
    myMusic.numberOfLoops = -1; 
    [myMusic play];
}


- (IBAction) scoreView {

    ScoreViewController *scoreView = [[ScoreViewController alloc] initWithNibName:@"ScoreViewController" bundle:nil];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:1];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
    [self.view addSubview: scoreView.view];
    [UIView commitAnimations];
}

EDITED CODE :

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
        if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {

            NSString * musicSonati = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
            myMusic = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicSonati] error:NULL];
            myMusic.delegate = self;
            myMusic.numberOfLoops = -1;
            [myMusic play];

        }
        return self;
    }

//toggle button
- (IBAction)MusicPlaying:(id)sender {

    if ((isPlay = !isPlay))
    {

        UIImage *buttonImageNormal = [UIImage imageNamed:@"play.png"]; 
        UIImage *stretchableButtonImageNormal = [buttonImageNormal  stretchableImageWithLeftCapWidth:0 topCapHeight:0]; 
        [MusicButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal]; 
        [myMusic pause];



    }else {

        UIImage *buttonImageNormal = [UIImage imageNamed:@"pause.png"]; 
        UIImage *stretchableButtonImageNormal = [buttonImageNormal  stretchableImageWithLeftCapWidth:0 topCapHeight:0]; 
        [MusicButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal]; 
        NSLog(@"Music play");
        [myMusic play];

    } 

}

回答1:

Make sure myMusic is correctly declared as a retained property and synthesized then try something like this:

-(void) commonInit {
    NSString * musicSonati = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
    self.myMusic = [[[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicSonati] error:NULL] autorelease];
    self.myMusic.delegate = self;
    self.myMusic.numberOfLoops = -1;
//You probably don't want to play music on init, rather defer to viewDidLoad.
//        [self.myMusic play];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (id)init {
    self = [super init];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        [self commonInit];
    }
    return self;
}

Then try this in your viewDidLoad:

- (void)viewDidLoad {
    ...
    if (!self.myMusic.playing) {
        [self.myMusic play];
    }
    ...
}

Also, don't forget to release your player in dealloc!



回答2:

If you have audio to play on multiple places then one simple way to achieve this is declare AVAudioPlayer instance in delegate with property synthesized.If you want to play this anywhere do this:-

MyAppDelegate *app_delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];


if(app_delegate.audioPlayer)
{
    [app_delegate.audioPlayer release];
    app_delegate.audioPlayer = nil;
}
app_delegate.audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];     

and if you want to stop sound do this:-

if(app_delegate.audioPlayer)
{
    if([app_delegate.audioPlayer isPlaying])
    {
        [app_delegate.audioPlayer stop];
        [app_delegate.audioPlayer setCurrentTime:0];
    }
}

and to play new sound file release and nil same player if already allocated or alloc it again with new sound file url.



回答3:

First, viewDidLoad probably isn't a good place to be initializing your AVAudioPlayer, as the system may need to unload some of your components to reclaim memory (in viewDidUnload). You should probably be creating the AVAudioPlayer in your init method or similar.

So what's happening is you end up creating a second AVAudioPlayer when the focus comes back to your application, and you're actually losing the reference to your first one. (Thus, also leaking memory.)

If you want to start playing music when the view loads, you should additionally check its status before doing so:

- (void)viewDidLoad {
    ...
    if (!myMusic.playing) {
        [myMusic play];
    }
    ...
}


回答4:

Its seems you are developing game (from your function name After viewLoad (ScoreView). ;) )

Well, According to me, AvAudioplayer is not Good Option if you want to implement with Game.

Use cocosdenshion, Download the latest cocos2d folder, find the these 9 files, put it in your resource folder,

And You are done.. !!!

#import "SimpleAudioEngine.h" // wherever you want to call in head part of the file.

Step1 call short file.!

[[SimpleAudioEngine sharedEngine] playEffect:@"blast.mp3"];

step2 call background loop.

[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background.mp3" loop:YES];

NOTE: There are list of available function http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_simple_audio_engine.html , Its very easy and simple !

Whole implementation will take, 20 minutes max !



回答5:

Initialize your player in app delegate file and play your background music. Only set one variable in app delegate which checks music play true or false...and enjoy your app without restarting music......

In your code you initialize you player in view did load and init method... that's why you music restart.....just call it only once in app delegate applicationdidfinshLaunching() method....