xcode iOS SDK:后台播放音乐和切换视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8467533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:43:55  来源:igfitidea点击:

iOS SDK : playing music on the background and switching views

iphoneiosxcodeipad

提问by Mc.Lover

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 :

我正在尝试在我的应用程序中播放音乐。音乐效果很好,但在切换 viewControllers 并返回主菜单后,我的音乐再次播放!这意味着几个相同的声音一起播放!我该如何解决这个问题?这是我的代码:

- (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];

    } 

}

采纳答案by Cliff

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

确保 myMusic 被正确声明为保留属性并合成,然后尝试如下操作:

-(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:

然后在你的 viewDidLoad 中试试这个:

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

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

另外,不要忘记在 dealloc 中释放您的播放器!

回答by Dhawal

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:-

如果您要在多个地方播放音频,那么实现此目的的一种简单方法是使用合成属性在委托中声明 AVAudioPlayer 实例。如果您想在任何地方播放,请执行以下操作:-

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.

并播放新的声音文件释放和 nil 相同的播放器(如果已经分配或使用新的声音文件 url 再次分配)。

回答by Craig Otis

First, viewDidLoadprobably 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 AVAudioPlayerin your initmethod or similar.

首先,viewDidLoad可能不是初始化 的好地方AVAudioPlayer,因为系统可能需要卸载某些组件以回收内存(在 中viewDidUnload)。您可能应该AVAudioPlayer在您的init方法或类似方法中创建。

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

所以发生的事情是AVAudioPlayer当焦点回到你的应用程序时你最终创建了第二个,而你实际上失去了对第一个的引用。(因此,也会泄漏内存。

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];
    }
    ...
}

回答by max9xs

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

看来您正在开发游戏(来自您的函数名称 After viewLoad (ScoreView). ;) )

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

好吧,据我所知,如果您想使用 Game 实现,AvAudioplayer 不是一个好选择。

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

使用cocosdenshion,下载最新的cocos2d文件夹,找到这9个文件,放到你的资源文件夹中,

And You are done.. !!!

你完成了.. !!!

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

Step1 call short file.!

Step1 调用短文件。!

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

step2 call background loop.

step2 调用后台循环。

[[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 !

注意:有可用功能列表http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_simple_audio_engine.html,非常简单!

Whole implementation will take, 20 minutes max !

整个实施最多需要 20 分钟!

回答by Anshul Jain

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....

在你的代码中,你在视图中初始化你的播放器确实加载和初始化方法......这就是你音乐重启的原因......只需在应用程序委托 applicationdidfinshLaunching() 方法中调用它一次......