使用AVAudioPlayer播放多个audio文件

我在主StoryBoard上创build了3个UIButtons。

当我按下“button1”或“button2”时,每个播放audio文件(“播放器1”,“播放器2”)。当audio播放时,UIButton被设置为selected

我想“Button3”在一行中实现多个函数。 这意味着当我按下“button3”时,应该首先播放“播放器3”,然后在“播放器1”之后播放“播放器2”。

然而,当我按下“Button3”时,同时播放“播放器1”和“播放器2”,因为前一个结束没有延迟。

我发现设置AVAudioPlayer的代理或使用AVQueuePlayer将解决这个问题,但是我发现很难做出改变。

我创造了图像,使其更容易理解

  fileprivate var player1:AVAudioPlayer? fileprivate var player2:AVAudioPlayer? fileprivate var player3:AVAudioPlayer? @IBAction func pushButton1(sender: UIButton) { audioPlayer1(url: url1) } @IBAction func pushButton2(sender: UIButton) { audioPlayer2(url: url2) } @IBAction func pushButton3(_ sender: UIButton) { audioPlayer3(url: url1, url2: url2, url3: url3) } func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { if (player === player1) { yourButton1.isSelected = false } else if (player === player2) { yourButton2.isSelected = false } else if (player === player3) { //"player 1" and "player 2" are played at same time yourButton3.isSelected = false player1!.play() yourButton1.isSelected = true player2!.play() yourButton2.isSelected = false } } func audioPlayer1(url: URL) { do { try player1 = AVAudioPlayer(contentsOf:url) player1!.play() yourButton1.isSelected = true player1!.delegate = self } catch { print(error) } } func audioPlayer2(url: URL) { do { try player2 = AVAudioPlayer(contentsOf:url) player2!.play() yourButton2.isSelected = true player2!.delegate = self } catch { print(error) } } func audioPlayer3(url: URL, url2: URL, url3: URL) { do { try player3 = AVAudioPlayer(contentsOf:url3) try player1 = AVAudioPlayer(contentsOf: url1) try player2 = AVAudioPlayer(contentsOf: url2) player3!.play() yourButton3.isSelected = true player3!.delegate = self player1!.delegate = self } catch { print(error) } } } 

更改了代码

  var queue = AVQueuePlayer() var items = [AVPlayerItem]() override func viewDidLoad() { super.viewDidLoad() player1?.delegate = self player2?.delegate = self player3?.delegate = self let asset1 = AVPlayerItem(url: url1) let asset2 = AVPlayerItem(url: url2) let asset3 = AVPlayerItem(url: url3) let asset4 = AVPlayerItem(url: url4) items = [asset1, asset2, asset3, asset4] queue = AVQueuePlayer(items: items) for item in queue.items() { NotificationCenter.default.addObserver(self, selector: #selector(playerItemDidReachEnd(notification:)), name: .AVPlayerItemDidPlayToEndTime, object: item) } } @IBAction func pushButton3(_ sender: UIButton) { //audioPlayer3(url: url1, url2: url2) sender.isSelected = true queue.play() } func playerItemDidReachEnd(notification: NSNotification) { if notification.object as? AVPlayerItem == items[0] { yourButton3.isSelected = false yourButton1.isSelected = true } if notification.object as? AVPlayerItem == items[1] { yourButton1.isSelected = false yourButton2.isSelected = true } if notification.object as? AVPlayerItem == items[2] { yourButton2.isSelected = false yourButton4.isSelected = true //yourButton1.isSelected = true } if notification.object as? AVPlayerItem == items[3] { yourButton4.isSelected = false print("item 3") } 

编辑: 这是 AVAudioPlayer 的方法

所以基本上:

1:只添加一名玩家,移除其余的玩家。

2:用您想要播放的对象创build一个 NSMutableArray

3:根据按下的button,你可以重新安排NSMutableArray对象来设置正确的顺序,如你所愿。 (如果你想简单地重新创build数组),然后开始播放数组中的firstObject (url),并将其添加到播放器中。

4:玩家完成游戏后,可以像上面那样开始播放下一个将NSMutableArray添加到玩家的对象。

以上步骤将避免多个玩家同时玩,以及其他好处(如避免同时加载多个URL等)

您可能需要一些variables来检查currentPlayingObject以确定下一个是哪一个,也可能是一个int ,并检查是否不尝试从数组中加载新项目(如果它是最后一个项目),以避免在访问objectAtIndex时发生崩溃那不存在。