AVAudioPlayer立即停止播放ARC

我试图通过AVAudioPlayer播放MP3,我认为这很简单。 不幸的是,这不是工作。 这是我所做的一切:

  • 为了testing,我在Xcode中创build了一个新的iOS应用程序(Single View)。
  • 我将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]; } 

不幸的是,audio开始播放后显然停止。 如果我取消注释sleepForTimeInterval它播放20秒,然后停止。 只有使用ARC进行编译时才会出现此问题,否则,该工作将完美无瑕。

问题是,在编译ARC时,你需要确保保持对你想保持活动的实例的引用,因为编译器会通过插入release调用来自动修复“不平衡”的alloc (至less在概念上,阅读Mikes Ash博客文章更多细节 )。 您可以通过将实例分配给属性或实例variables来解决此问题。

在Phlibbo案例中,代码将被转换为:

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

而且AVAudioPlayer会立即停止播放,因为当没有引用时它会被释放。

我自己并没有使用ARC,只是简单地阅读了一下。 请评论我的答案,如果你知道更多关于这个,我会更新与更多的信息。

更多的ARC信息:
过渡到ARC发行说明
LLVM自动引用计数

如果您需要同时播放多个AVAudioPlayers,请创build一个NSMutableDictionary。 将密钥设置为文件名。 通过代理callback从字典中移除,如下所示:

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

使用AVAudioPlayer作为strong的头文件中的伊娃:

 @property (strong,nonatomic) AVAudioPlayer *audioPlayer