AVQueuePlayer音频无法播放

时间:2014-12-14 08:43:38

标签: ios objective-c audio avplayer avqueueplayer

我有一个AVQueuePlayer属性,设置如下。 NSLog语句报告音频应该正常播放(当应用程序运行时)但是在模拟器和iOS设备本身(iPhone 5s iOS 8.1.1)上进行测试时,没有音频播放。

我已确认设备没有静音,并且已达到最大音量。我正在使用Xcode 6和iOS 8 SDK。我在“链接二进制文件”部分导入AVFoundation框架并将其导入我的类。

-(void)viewDidLoad
{
   [super viewDidLoad];
   [self music];
   // other setup code
}


- (void)music
{
    music = [[NSMutableArray alloc]initWithArray:@[
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM1"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM2"
                                                                                                                                        ofType:@"mp3" ]]],
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM3"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM4"
                                                                                                                                        ofType:@"mp3" ]]],
                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM5"
                                                                                                                                        ofType:@"mp3" ]]],

                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM6"
                                                                                                                                        ofType:@"mp3" ]]],



                                                   [AVPlayerItem playerItemWithURL:[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"BM7"
                                                                                                                                        ofType:@"mp3" ]]]



                                                   ]];


    for(AVPlayerItem *a in music)
    {

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:a];

    }

    [music shuffle];

    self.audio  = [[AVQueuePlayer alloc]initWithItems:music];


    [self.audio play];



    NSLog(@"Now playing%@",[self.audio currentItem]);

    NSLog(@"%@",self.audio);









}
-(void)playerItemFinished:(NSNotification *)notification
{
    if([[self.audio currentItem] isEqual:[music lastObject]])
    {

        self.audio = nil;

        [music shuffle];

        self.audio = [[AVQueuePlayer alloc]initWithItems:music];


        [self.audio play];

    }

}

2 个答案:

答案 0 :(得分:1)

尝试以这种方式构建数组:

music = [[NSMutableArray alloc] initWithArray:@[[AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM1" withExtension:@"mp3"]],...]];

编辑: 无论如何,恕我直言,最重要的方面是突出显示withExtension工作的原因,其中ofType不能:第一个返回由指定名称和文件扩展名标识的资源的文件URL,其中-pathForResource:ofType:返回完整路径名对于由指定名称和文件扩展名标识的资源。但是,您需要一个NSURL对象来初始化AVPlayer,而AVQueuePlayer是AVPlayer的子类,您可以使用它来按顺序播放多个项目。

答案 1 :(得分:0)

好吧,我已经从上面的评论中创建了一个代码段,因此您可以将其复制粘贴到您的项目中。

我基本上做了2次改变 数组创建已从initWithArray:更改为initWithObjects:,因此您无法创建新的不必要的未使用数组,该数组可能会在此方法调用后解除分配。
另外,不是在该数组中的每个对象上调用[NSURL URLWithString:[[NSBundle mainBundle] pathForResource:ofType:]]],而是只需调用[[NSBundle mainBundle] URLForResource:withExtension:

music = [[NSMutableArray alloc] initWithObjects:
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM1" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM2" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM3" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"BM4" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP5" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP6" withExtension:@"mp3"]],
                          [AVPlayerItem playerItemWithURL:[[NSBundle mainBundle] URLForResource:@"MP7" withExtension:@"mp3"]],
                          nil];  
祝你好运。

编辑 -
我不是母语为英语的人,所以我会尽力明白 如果某些事情不清楚,请告诉我,我会尝试对其进行改写。

initWithArray所做的是创建一个新数组,包含给定数组的内容,
例如:

NSArray *array1 = [[NSArray alloc] initWithObjects:@"One", @"Two", @"Three", nil]];  
NSArray *array2 = [[NSArray alloc] initWithArray:array1];  

所以现在array1array2都有相同的项目。

如果我没弄错,从Xcode 4开始,引入了一种创建数组的新方法,现在,不是调用[[NSArray alloc] initWithObjects:],而是使用{{1}简单地创建一个包含对象的数组语法。
所以我们上面的例子看起来像这样:

@[]

那么你在原始代码中做了什么,基本上是调用NSArray *array1 = @[@"One", @"Two", @"Three"]; // Notice that 'nil' is not necessary NSArray *array2 = [[NSArray alloc] initWithArray:array2]; ,最终会创建一个新数组,

然后,使用' new' [[NSMutableArray alloc] initWithObjects:]语法,您已创建另一个包含所有@[]个对象的新数组,
并且'告诉' AVPlayerItem数组,以包含该新数组的内容。

所以在这个'单行'代码,你实际上创建了2个不同的数组 这个' new'未命名的数组可能在该行之后被释放,因为你在任何地方都没有任何对该数组的引用(你只是在新创建的数组中引用了它的对象),
ARC自动释放引用计数为零的对象。

由于这个原因,您可能不会感到任何记忆/性能问题 但我认为有必要指出这一点,因为它是不必要的,它并不是“正确的”。实现你正在尝试的方法,现在代码看起来更干净,更可读。

BTW-
这不是您的代码无法正常工作的原因 您遇到的问题是您的原始代码生成music并将路径作为字符串:NSURL
/PATH/TO/MY/MP3期望路径为网址:AVPlayerItem
(您可以file:///PATH/TO/MY/MP3新旧呼叫来验证不同的输出)