无法在iPhone游戏中播放mp3文件
我想在游戏中播放背景音乐(理想情况下,我希望它淡入/淡出,但我想先播放) 我已经在SO上查看了各种答案,我的代码看起来似乎是正确的,但由于某种原因,文件没有播放,事实上它在无法在iPhone游戏中播放mp3文件,iphone,ios,objective-c,avaudioplayer,Iphone,Ios,Objective C,Avaudioplayer,我想在游戏中播放背景音乐(理想情况下,我希望它淡入/淡出,但我想先播放) 我已经在SO上查看了各种答案,我的代码看起来似乎是正确的,但由于某种原因,文件没有播放,事实上它在AVAudioPlayer*player行上崩溃(没有有用的输出)。如果我继续,它会在[player play]行再次崩溃,但错误是0 已更新。。。再次 GameViewController.h @property (nonatomic, retain) AVAudioPlayer *player; GameViewCont
AVAudioPlayer*player
行上崩溃(没有有用的输出)。如果我继续,它会在[player play]
行再次崩溃,但错误
是0
已更新。。。再次
GameViewController.h
@property (nonatomic, retain) AVAudioPlayer *player;
GameViewController.m
@synthesize player; // the player object
ViewDidLoad:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: @"bgtrack" ofType: @"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error: nil]; // breaks here
[player prepareToPlay];
包括我在内
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#导入
#进口
更新:
根据评论,我尝试直接从苹果开发中心复制/粘贴代码。我正在使用最新的XCode 4和iOS 6.1模拟器
当它崩溃时,我得不到任何信息栏,因为它碰到了一个断点。该文件包含在捆绑包中您需要存储对
播放器
的强引用(可能在视图控制器的ivar中或其他地方)。如果您只是将该代码放入-viewDidLoad
方法或其他方法中,而没有对其进行强引用,那么将发生的情况是,玩家将在有机会开始玩之前被释放。例如:
@interface MyViewController : UIViewController
@end
@implementation MyViewController
{
AVAudioPlayer* player;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"YourMP3FileName" ofType:@"mp3"];
NSURL *soundFileURL = [NSURL fileURLWithPath:soundFilePath];
NSError *error;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundFileURL error:&error];
player.numberOfLoops = -1; //infinite
player.currentTime = 139;// 2:19;
[player play];
}
@end
这对我来说很好,但是如果player
不是视图控制器的ivar,我就不会听到声音
另外,我还开设了以下课程,将作为“一次性”AVAudioPlayer使用。对于numberOfLoops
为-1(无限)的情况,这显然是一个问题,因为这意味着它永远不会停止播放或消失,但如果您希望播放某个内容一次,然后消失,而不需要保留对它的引用,则可能会使事情稍微容易一些
OneShotAVAudioPlayer.h
#import <AVFoundation/AVFoundation.h>
@interface OneShotAVAudioPlayer : AVAudioPlayer
@end
#导入。将播放器ivar升级为强属性,如果播放器为零,则记录[错误描述]
如果它崩溃了,肯定是出了问题。您添加了异常断点吗?谢谢,这是一个很好的建议,但当我执行您的建议时,它仍然崩溃。我似乎没有得到任何输出或它发生的原因?异常/崩溃的回溯是什么?(只需编辑问题——不可能阅读SO评论中的回溯)我没有得到任何异常信息,这很奇怪,它只是停止执行,不再说什么。您是否将音频文件包括在捆绑包中?是的,但仍然没有乐趣:/详细说明问题:什么设备?还是模拟器?Ios版本?在github上共享资源?您是否尝试过Apple的示例代码?已更新。尝试了你所有的建议,但仍然没有进一步的进展:/所以只是模拟器不起作用?你试过真正的设备吗?因为模拟器不播放声音存在已知问题。我目前已经在@界面
中定义了它,比如so@属性(强,非原子)AVAudioPlayer*BackgroundMusicPlayer代码>但仍然不起作用。没有错误信息:/I我为所有异常设置了一个断点,但我没有得到任何关于实际发生情况的信息:/I正如我在顶部评论的那样,发布代码,尝试示例代码,更改mp3,检查音量,做一点家庭作业。
#import "OneShotAVAudioPlayer.h"
#import <AVFoundation/AVFoundation.h>
#import <objc/runtime.h>
@interface OneShotAVAudioPlayer () <AVAudioPlayerDelegate>
@property(weak) id<AVAudioPlayerDelegate> p_exogenousDelegate;
@end
@implementation OneShotAVAudioPlayer
static void * const OneShotAVAudioPlayerKey = (void*)&OneShotAVAudioPlayerKey;
- (id)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError
{
if (self = [super initWithContentsOfURL:url error:outError])
{
// Retain ourself
objc_setAssociatedObject(self, OneShotAVAudioPlayerKey, self, OBJC_ASSOCIATION_RETAIN);
[super setDelegate: self];
}
return self;
}
- (id)initWithData:(NSData *)data error:(NSError **)outError;
{
if (self = [super initWithData:data error:outError])
{
// Retain ourself
objc_setAssociatedObject(self, OneShotAVAudioPlayerKey, self, OBJC_ASSOCIATION_RETAIN);
[super setDelegate: self];
}
return self;
}
- (void)setDelegate:(id<AVAudioPlayerDelegate>)delegate
{
self.p_exogenousDelegate = delegate;
}
- (id<AVAudioPlayerDelegate>)delegate
{
return self.p_exogenousDelegate;
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
@try
{
if ([self.p_exogenousDelegate respondsToSelector: _cmd])
[self.p_exogenousDelegate audioPlayerDidFinishPlaying:player successfully:flag];
}
@finally
{
// Make a strong ref so we stay alive through the scope of this function
typeof(self) keepAlive = self;
// Give up the self retain
objc_setAssociatedObject(keepAlive, OneShotAVAudioPlayerKey, nil, OBJC_ASSOCIATION_RETAIN);
// Push in the "real" (outside) delegate, cause our job is done here.
[super setDelegate: self.p_exogenousDelegate];
}
}
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error
{
@try
{
if ([self.p_exogenousDelegate respondsToSelector: _cmd])
[self.p_exogenousDelegate audioPlayerDecodeErrorDidOccur:player error:error];
}
@finally
{
// Make a strong ref so we stay alive through the scope of this function
typeof(self) keepAlive = self;
// Give up the self retain
objc_setAssociatedObject(keepAlive, OneShotAVAudioPlayerKey, nil, OBJC_ASSOCIATION_RETAIN);
// Push in the "real" (outside) delegate, cause our job is done here.
[super setDelegate: self.p_exogenousDelegate];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
BOOL retVal = [super respondsToSelector: aSelector];
if (!retVal)
{
struct objc_method_description method = protocol_getMethodDescription(@protocol(AVAudioPlayerDelegate), aSelector, YES, YES);
if (method.name)
{
retVal = [self.p_exogenousDelegate respondsToSelector: aSelector];
}
}
return retVal;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
id retVal = [super forwardingTargetForSelector:aSelector];
if (!retVal)
{
struct objc_method_description method = protocol_getMethodDescription(@protocol(AVAudioPlayerDelegate), aSelector, YES, YES);
if (method.name && [self.p_exogenousDelegate respondsToSelector: aSelector])
{
retVal = self.p_exogenousDelegate;
}
}
return retVal;
}
- (void)setNumberOfLoops:(NSInteger)numberOfLoops
{
if (numberOfLoops < 0)
{
NSLog(@"Warning! You have set an infinite loop count for an instance of %@ (%p). This means the instance will effectively be leaked.", NSStringFromClass([self class]), self);
}
[super setNumberOfLoops: numberOfLoops];
}
@end