我试图通过AVAudioPlayer
播放MP3,我觉得这很简单。不幸的是,它并没有完全奏效。以下是我所做的一切:
我将AVFoundation框架添加到项目中,并将#import
<AVFoundation/AVFoundation.h>
添加到ViewController.m
我在应用'文档'文件夹中添加了一个MP3文件。
我将ViewControllers
viewDidLoad:
更改为以下内容:
代码:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil];
audioPlayer.numberOfLoops = 1;
[audioPlayer play];
//[NSThread sleepForTimeInterval:20];
}
不幸的是,音频在开始播放后显然会立即停止。如果我取消注释sleepForTimeInterval
它播放20秒并在之后停止。只有在使用ARC进行编译时才会出现此问题,否则,它会完美无缺地运行。
答案 0 :(得分:7)
问题在于,在使用ARC进行编译时,您需要确保保留对要保持活动的实例的引用,因为编译器将通过插入{{自动修复“不平衡”alloc
。 1}}调用(至少在概念上,阅读Mikes Ash blog post for more details)。您可以通过将实例分配给属性或实例变量来解决此问题。
在Phlibbo案例中,代码将转换为:
release
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* recorderFilePath = [NSString stringWithFormat:@"%@/MySound.mp3", [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:recorderFilePath] error:nil];
audioPlayer.numberOfLoops = 1;
[audioPlayer play];
[audioPlayer release]; // inserted by ARC
}
它会立即停止播放,因为在没有参考时会被取消分配。
我自己没有使用ARC,只是简单地阅读了它。如果您对此有更多了解,请对我的答案发表评论,我会更新更多信息。
更多ARC信息:
Transitioning to ARC Release Notes
LLVM Automatic Reference Counting
答案 1 :(得分:3)
使用strong
@property (strong,nonatomic) AVAudioPlayer *audioPlayer
答案 2 :(得分:3)
如果您需要同时播放多个AVAudioPlayers,请创建一个NSMutableDictionary。将密钥设置为文件名。通过委托回调从Dictionary中删除,如下所示:
-(void)playSound:(NSString*)soundNum {
NSString* path = [[NSBundle mainBundle]
pathForResource:soundNum ofType:@"m4a"];
NSURL* url = [NSURL fileURLWithPath:path];
NSError *error = nil;
AVAudioPlayer *audioPlayer =[[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
audioPlayer.delegate = self;
if (_dictPlayers == nil)
_dictPlayers = [NSMutableDictionary dictionary];
[_dictPlayers setObject:audioPlayer forKey:[[audioPlayer.url path] lastPathComponent]];
[audioPlayer play];
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[_dictPlayers removeObjectForKey:[[player.url path] lastPathComponent]];
}