2017-02-19 100 views
0

我在主StoryBoard上創建了3個UIButton。使用AVAudioPlayer播放多個音頻文件

當我按下「按鈕1」或「按鈕2」時,每個播放音頻文件(「播放器1」,「播放器2」),並且在播放音頻時,UIButton被設置爲selected

我想「按鈕3」在一行中實現多個功能。 這意味着當我按下「按鈕3」時,應該首先播放「播放器3」,然後在「播放器1」之後播放「播放器2」。

但是,當我按下「Button3」時,同時播放「player1」和「player2」,因爲前一個結束沒有延遲。

我發現設置AVAudioPlayer的代理或使用AVQueuePlayer可以解決問題,但我發現很難進行更改。

I created image to make it easier to understand

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") 
     } 
+0

檢查這個答案,你會得到更好的主意:http://stackoverflow.com/a/42273177/4033273 –

+0

@MoinShirazi使用AppDelegate不是用於這些類型的事情,這是違背最佳做法。 – 2017-02-19 07:55:30

回答

1

編輯:This is the methodAVAudioPlayer

所以基本上:

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

2:Create anNSMutableArray與您想要播放的對象。

3:根據按下哪個按鈕,您可以重新安排NSMutableArray對象以設置正確的順序。 (如果你想讓它變得簡單,只需重新創建陣列)並開始播放陣列中的firstObject(url),並相應地將其添加到播放器中。

4:當玩家完成遊戲時,您可以開始播放下一個對象,從NSMutableArray將其添加到您的播放器,就像上面所做的一樣。

按照以上步驟將避免多個玩家在玩同時放,加上其他福利(如避免在同一時間等加載多個URL)

你可能需要一些變量來檢查currentPlayingObject,以確定哪一個是下一個,可能是int,並檢查是否不嘗試從數組中加載新項目(如果它是最後一個項目),以避免在訪問不存在的objectAtIndex時發生崩潰。

+0

嗯我重寫了通知觀察員的代碼,但我收到多個錯誤...你會告訴我它應該如何看上面的代碼?我也很難理解「改變同一個播放器的項目/網址並開始播放」的意思。/ – rebecca87

+0

@ rebecca87對不起,我的錯誤是,我誤以爲您的播放器是AVPlayer。我已經更新了答案。不幸的是,我並沒有在Swift中編寫代碼,但如果你遵循我寫的內容,它應該是非常直截了當的。 – 2017-02-19 07:46:24

+0

感謝您的幫助。我會嘗試重寫我的代碼。 – rebecca87

相關問題