Player1 works well ,but I have an error implementing Player2.
How should I change audioPlayerDidFinishPlaying to make it work?
Here is the code for my ViewController.swift:
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if (player === player2) {
yourButton2.isSelected = false
} else {
yourButton.isSelected = false
player2!.play()
yourButton2.isSelected = false
}
}
func Player1(url: URL) {
do {
try player2 = AVAudioPlayer(contentsOf:url)
player2!.play()
yourButton2.isSelected = true
player2!.delegate = self
} catch {
print(error)
}
}
func Player2(url: URL, url2: URL) {
do {
try player1 = AVAudioPlayer(contentsOf:url)
try player2 = AVAudioPlayer(contentsOf: url2)
player1!.play()
yourButton.isSelected = true
player1!.delegate = self
} catch {
print(error)
}
}
In audioPlayerdidFinishPlaying(_:successfully:) you have a else if-clause that will never become true:
} else if (player === player3) {
player3 will always be nil because you are never assigning something to it. Thus your 3rd branch in audioPlayerdidFinishPlaying(_:successfully:) will never be executed. To make this work within you current class design, you need to either:
Change the else if clause
Assign something to player3
Related
To put it in context, I'm developing an app that is recording a lot of time while in background or in the app. I'm facing two problems using AVAudioRecorder to record in my app:
My recording resumes fine when, for example, I play an audio in WhatsApp or a video in Instagram. But when I play a song in Apple Music or a play a voice note, it doesn't resume the recording again.
If I'm in a Phone Call and I start the recording, my app crashes and outputs the following:
(Error de OSStatus 561017449.)
I think also need to handle when the input/output device changes so my app doesn't crash.
The code that I implemented for the class where I'm recording (and also playing the sound I use recorder so I can try it and see if it works) is this:
class RecordViewController: UIViewController, AVAudioPlayerDelegate , AVAudioRecorderDelegate {
#IBOutlet weak var principalLabel: UILabel!
#IBOutlet weak var loginLabel: UILabel!
#IBOutlet weak var recordBTN: UIButton!
#IBOutlet weak var playBTN: UIButton!
var audioRecorder : AVAudioRecorder!
var audioPlayer : AVAudioPlayer!
var isAudioRecordingGranted: Bool!
var isRecording = false
var isPlaying = false
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
check_record_permission()
checkActivateMicrophone()
NotificationCenter.default.addObserver(self, selector: #selector(handleInterruption(notification:)), name: AVAudioSession.interruptionNotification, object: audioRecorder)
let tapRegister: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.goToLogin))
loginLabel.addGestureRecognizer(tapRegister)
loginLabel.isUserInteractionEnabled = true
}
#objc func goToLogin() {
self.performSegue(withIdentifier: "goToLogin", sender: self)
}
#objc func handleInterruption(notification: Notification) {
guard let userInfo = notification.userInfo,
let typeInt = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
let type = AVAudioSession.InterruptionType(rawValue: typeInt) else {
return
}
switch type {
case .began:
if isRecording {
print("OOOOOOO")
audioRecorder.pause()
}
break
case .ended:
guard let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt else { return }
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
if options.contains(.shouldResume) {
audioRecorder.record()
print("AAAAAAA")
} else {
print("III")
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.audioRecorder.record()
}
}
default: ()
}
}
func check_record_permission()
{
switch AVAudioSession.sharedInstance().recordPermission {
case AVAudioSessionRecordPermission.granted:
isAudioRecordingGranted = true
break
case AVAudioSessionRecordPermission.denied:
isAudioRecordingGranted = false
break
case AVAudioSessionRecordPermission.undetermined:
AVAudioSession.sharedInstance().requestRecordPermission({ (allowed) in
if allowed {
self.isAudioRecordingGranted = true
} else {
self.isAudioRecordingGranted = false
}
})
break
default:
break
}
}
func checkActivateMicrophone() {
if !isAudioRecordingGranted {
playBTN.isEnabled = false
playBTN.alpha = 0.5
recordBTN.isEnabled = false
recordBTN.alpha = 0.5
principalLabel.text = "Activa el micrófono desde ajustes"
} else {
playBTN.isEnabled = true
playBTN.alpha = 1
recordBTN.isEnabled = true
recordBTN.alpha = 1
principalLabel.text = "¡Prueba las grabaciones!"
}
}
func getDocumentsDirectory() -> URL
{
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
func getFileUrl() -> URL
{
let filename = "myRecording.m4a"
let filePath = getDocumentsDirectory().appendingPathComponent(filename)
return filePath
}
func setup_recorder()
{
if isAudioRecordingGranted
{
let session = AVAudioSession.sharedInstance()
do
{
try session.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker)
try session.setActive(true)
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue
]
audioRecorder = try AVAudioRecorder(url: getFileUrl(), settings: settings)
audioRecorder.delegate = self
audioRecorder.isMeteringEnabled = true
audioRecorder.prepareToRecord()
}
catch let error {
print(error.localizedDescription)
}
}
else
{
print("AAAAA")
}
}
#IBAction func recordAct(_ sender: Any) {
if(isRecording) {
finishAudioRecording(success: true)
recordBTN.setTitle("Record", for: .normal)
playBTN.isEnabled = true
isRecording = false
}
else
{
setup_recorder()
audioRecorder.record()//aaaaaa
recordBTN.setTitle("Stop", for: .normal)
playBTN.isEnabled = false
isRecording = true
}
}
func finishAudioRecording(success: Bool)
{
if success
{
audioRecorder.stop()
audioRecorder = nil
print("recorded successfully.")
}
else
{
print("Recording failed.")
}
}
func prepare_play()
{
do
{
audioPlayer = try AVAudioPlayer(contentsOf: getFileUrl())
audioPlayer.delegate = self
audioPlayer.prepareToPlay()
}
catch{
print("Error")
}
}
#IBAction func playAct(_ sender: Any) {
if(isPlaying)
{
audioPlayer.stop()
recordBTN.isEnabled = true
playBTN.setTitle("Play", for: .normal)
isPlaying = false
}
else
{
if FileManager.default.fileExists(atPath: getFileUrl().path)
{
recordBTN.isEnabled = false
playBTN.setTitle("pause", for: .normal)
prepare_play()
audioPlayer.play()
isPlaying = true
}
else
{
print("Audio file is missing.")
}
}
}
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool)
{
if !flag
{
print("UUU")
finishAudioRecording(success: false)
}
playBTN.isEnabled = true
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
recordBTN.isEnabled = true
}
}
I implemented the "Background Mode" of Audio, AirPlay and Picture in Picture
I am playing an audio which can be pausing, resuming and stoped I have also a slider which can be use to change the play the audio current point and a label that show duration of the audio and I want to pause the timer when the user pause the audio and I read If I want that I can invalidate and nill the timer then start it again , but the issue with that it will replay the audio from the start, is there is way to start the timer at the last point it was paused?
func startTimer() {
if replayTimer == nil {
replayTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateSlider), userInfo: nil, repeats: true)
}
}
#objc func updateSlider() {
progressBar.value = Float(audio.audio!.currentTime)
}
#IBAction func playReceiverVoicenote(_ sender: Any) {
if replayTimer == nil {
audioBtn.setImage(#imageLiteral(resourceName: "pause"), for: .normal)
audio.playAudio(filePath: filePath!)
startTimer()
receiverProgressBar.maximumValue = audio.getAudioDuration()
} else if audio.isAudioPlaying() {
audioBtn.setImage(#imageLiteral(resourceName: "playAudio"), for: .normal)
audio.pauseAudio()
replayTimer?.invalidate()
replayTimer = nil
} else {
audioBtn.setImage(#imageLiteral(resourceName: "pause"), for: .normal)
audio.replayAudio()
startTimer()
}
}
func playAudio(filePath:URL){
do {
audio = try AVAudioPlayer(contentsOf: filePath)
audio!.delegate = self
audio!.prepareToPlay()
audio!.volume = 1.0
audio!.play()
} catch {
print(error.localizedDescription)
}
}
func pauseAudio() {
audio!.pause()
}
func replayAudio() {
audio!.play()
}
func stopAudio() {
audio!.stop()
}
When the audio is going to pause save audio.currentTime in a variable and invalidate the timer.
When the audio is going to resume get the saved currentTime, call play(atTime:) passing the time interval and restart the timer
You can also use this Audio Manager in this way:
let player = AudioPlayer()
player.loadAudio(url: URL(string: "myAudioUrl.mp3")!, name: "", img: "")
And the action of the button to play and pause:
if player.isPlaying {
player.pauseAudio()
} else {
player.playAudio { isFinish, player, currentTimeInSec, remainingTimeInSec in
if isFinish {
// Audio finish to play
}
}
}
Who return in block closure:
isFinish: Bool // If the audio has finished playing
player: AVAudioPlayer // The player
currentTimeInSec: Int // The current time in seconds of the audio playing
remainingTimeInsec: Int // The remaining time
AudioPlayer:
import Foundation
import AVFoundation
import MediaPlayer
class AudioPlayer {
var audioPlayer: AVAudioPlayer?
var hasBeenPaused = false
var songName = ""
var songImage = ""
var timer: Timer?
var isPlaying: Bool {
return audioPlayer?.isPlaying ?? false
}
public func loadAudio(url: URL, name: String, img: String) {
songName = name
songImage = img
setupRemoteTransportControls()
do {
audioPlayer = try AVAudioPlayer(contentsOf: url)
audioPlayer?.prepareToPlay()
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playback, mode: .default)
} catch let sessionError {
print(sessionError)
}
} catch let songPlayerError {
print(songPlayerError)
}
}
public func playAudio(completion: ((_ isFinish: Bool, _ player: AVAudioPlayer, _ currentTimeInSec: Int, _ restTimeInSec: Int) -> ())? = nil) {
guard let audioPlayer = audioPlayer else { return }
audioPlayer.play()
setupNowPlaying()
if timer == nil {
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
let currentTime = Int(audioPlayer.currentTime)
let remainingTime = Int(audioPlayer.duration) - Int(currentTime)
if remainingTime == 0 {
completion?(true, audioPlayer, currentTime, remainingTime)
if self.timer != nil {
self.timer!.invalidate()
self.timer = nil
}
} else {
completion?(false, audioPlayer, currentTime, remainingTime)
}
}
}
}
public func pauseAudio() {
guard let audioPlayer = audioPlayer else { return }
if audioPlayer.isPlaying {
audioPlayer.pause()
hasBeenPaused = true
} else {
hasBeenPaused = false
}
setupNowPlaying()
if timer != nil {
timer!.invalidate()
timer = nil
}
}
public func replayAudio() {
guard let audioPlayer = audioPlayer else { return }
if audioPlayer.isPlaying || hasBeenPaused {
audioPlayer.stop()
audioPlayer.currentTime = 0
audioPlayer.play()
} else {
audioPlayer.play()
}
setupNowPlaying()
}
public func stopAudio() {
guard let audioPlayer = audioPlayer else { return }
audioPlayer.stop()
setupNowPlaying()
if timer != nil {
timer!.invalidate()
timer = nil
}
}
func setupRemoteTransportControls() {
let commandCenter = MPRemoteCommandCenter.shared()
commandCenter.previousTrackCommand.isEnabled = false
commandCenter.nextTrackCommand.isEnabled = false
commandCenter.skipBackwardCommand.isEnabled = false
commandCenter.skipForwardCommand.isEnabled = false
commandCenter.playCommand.isEnabled = true
commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
//Update your button here for the play command
self.playAudio()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updatedControlCenterAudio"), object: nil)
return .success
}
commandCenter.pauseCommand.isEnabled = true
commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
//Update your button here for the pause command
self.pauseAudio()
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updatedControlCenterAudio"), object: nil)
return .success
}
}
func setupNowPlaying() {
guard let audioPlayer = audioPlayer else { return }
var nowPlayingInfo = [String: Any]()
nowPlayingInfo[MPMediaItemPropertyTitle] = songName
if let image = UIImage(named: songImage) {
nowPlayingInfo[MPMediaItemPropertyArtwork] =
MPMediaItemArtwork(boundsSize: image.size) { size in
return image
}
}
nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = audioPlayer.currentTime
nowPlayingInfo[MPMediaItemPropertyPlaybackDuration] = audioPlayer.duration
nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = audioPlayer.rate
// Set the metadata
MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
}
}
I created the 4 UIButtons on the Main StoryBoard.
I would like "Button4" to implement the other buttons function in a row. That means when I press button 4, player 1 should be played first, after that player 2 and after that player 3.
However, when I press "Button4", "Button2" and "Button3" are played at same time.
fileprivate var player1:AVAudioPlayer?
fileprivate var player2:AVAudioPlayer?
fileprivate var player3:AVAudioPlayer?
let url1 = Bundle.main.bundleURL.appendingPathComponent("music1.mp3")
let url2 = Bundle.main.bundleURL.appendingPathComponent("music2.mp3")
let url3 = Bundle.main.bundleURL.appendingPathComponent("music3.mp3")
#IBAction func pushButton1(sender: UIButton) {
Player(url: url1)
}
#IBAction func pushButton2(sender: UIButton) {
Player1(url: url2)
}
#IBAction func pushButton3(_ sender: UIButton) {
Player2(url: url1, url2: url2, url3: url3)
}
//"yourButton2" and "yourButton3" is played at same time in this code at player2
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if (player === player1) {
yourButton.isSelected = false
} else if (player === player2) {
yourButton2.isSelected = false
} else if (player === player3) {
yourButton.isSelected = false
player2!.play()
yourButton2.isSelected = true
player2!.play()
yourButton3.isSelected = true
player1!.play()
}
}
func Player(url: URL) {
do {
try player1 = AVAudioPlayer(contentsOf:url)
player1!.play()
yourButton.isSelected = true
player1!.delegate = self
} catch {
print(error)
}
}
func Player1(url: URL) {
do {
try player2 = AVAudioPlayer(contentsOf:url)
player2!.play()
yourButton2.isSelected = true
player2!.delegate = self
} catch {
print(error)
}
}
func Player2(url: URL, url2: URL, url3: URL) {
do {
try player3 = AVAudioPlayer(contentsOf:url)
try player2 = AVAudioPlayer(contentsOf: url2)
try player1 = AVAudioPlayer(contentsOf: url3)
player3!.play()
yourButton.isSelected = true
player3!.delegate = self
player2!.delegate = self
player1!.delegate = self
} catch {
print(error)
}
}
Rather than using an AVAudioPlayer, how about an AVQueuePlayer?
Here's a quick example:
var files = ["file1", "file2", "file3"]
var player: AVQueuePlayer = {
var pathArray = [String]()
files.forEach { resource in
if let path = Bundle.main.path(forResource: resource, ofType: "mp3") {
pathArray.append(path)
}
}
var urlArray = [URL]()
pathArray.forEach { path in
urlArray.append(URL(fileURLWithPath: path))
}
var playerItems = [AVPlayerItem]()
urlArray.forEach { url in
playerItems.append(AVPlayerItem(url: url))
}
let player = AVQueuePlayer(items: playerItems)
player.actionAtItemEnd = AVPlayerActionAtItemEnd.advance
return player
}()
and in your button's action:
#IBAction func buttonTapped(_ sender: UIButton) {
files = ["file2", "file3", "file1"]
player.play()
}
Admittedly, this is pretty quick and dirty, but something kind of like this because we're passing the files array into the player. It shouldn't be too difficult to find more optimization for this code.
EDIT: realized I wasn't passing in an array of AVPlayerItems, so updated.
Edit....
Each of the buttons, 1, 2, 3 etc...will work but "push button 2" is a bit of a mix...
Anyway, reexplain?
I set the 4 UIButtons on the Main StoryBoard.
I would like "Button4" to implement the method of the other three Buttons in a row. (At first, plays an audio file and set selected "Button1" then "Button2" then "Button3")
However "Button2" and "Button3" are played at same time.
fileprivate var player1:AVAudioPlayer?
fileprivate var player2:AVAudioPlayer?
fileprivate var player3:AVAudioPlayer?
let url1 = Bundle.main.bundleURL.appendingPathComponent("music1.mp3")
let url2 = Bundle.main.bundleURL.appendingPathComponent("music2.mp3")
let url3 = Bundle.main.bundleURL.appendingPathComponent("music3.mp3")
#IBAction func pushButton1(sender: UIButton) {
Player(url: url1)
}
#IBAction func pushButton2(sender: UIButton) {
Player1(url: url2)
}
#IBAction func pushButton3(_ sender: UIButton) {
Player2(url: url1, url2: url2, url3: url3)
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if (player === player1) {
yourButton.isSelected = false
} else if (player === player2) {
yourButton2.isSelected = false
} else if (player === player3) {
yourButton.isSelected = false
player2!.play()
yourButton2.isSelected = true
player2!.play()
yourButton3.isSelected = true
player1!.play()
}
}
func Player(url: URL) {
do {
try player1 = AVAudioPlayer(contentsOf:url)
player1!.play()
yourButton.isSelected = true
player1!.delegate = self
} catch {
print(error)
}
}
func Player1(url: URL) {
do {
try player2 = AVAudioPlayer(contentsOf:url)
player2!.play()
yourButton2.isSelected = true
player2!.delegate = self
} catch {
print(error)
}
}
func Player2(url: URL, url2: URL, url3: URL) {
do {
try player3 = AVAudioPlayer(contentsOf:url)
try player2 = AVAudioPlayer(contentsOf: url2)
try player1 = AVAudioPlayer(contentsOf: url3)
player3!.play()
yourButton.isSelected = true
player3!.delegate = self
player2!.delegate = self
player1!.delegate = self
} catch {
print(error)
}
}
I believe that when you press button 4, player 1 should be played first, after that player 2 and after that player 3. For this task, the below code should work.
let url1 = Bundle.main.bundleURL.appendingPathComponent("music1.mp3")
let url2 = Bundle.main.bundleURL.appendingPathComponent("music2.mp3")
let url3 = Bundle.main.bundleURL.appendingPathComponent("music3.mp3")
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if (player === player1) {
yourButton.isSelected = false
yourButton2.isSelected = true
do {
//initialise player 2
player2 = try AVAudioPlayer(contentsOf: url2)
player2!.delegate = self
}catch {
}
player2!.play()
} else if (player === player2) {
yourButton3.isSelected = true
yourButton2.isSelected = false
do {
//initialise player 3
player3 = try AVAudioPlayer(contentsOf: url3)
player3!.delegate = self
}catch {
}
player3!.play()
} else if (player === player3) {
yourButton3.isSelected = false
}
}
I created the 3 UIButtons on the Main StoryBoard.
When I press "Button1" or "Button2" each plays an audio file ( "player 1" , "player 2".) and while the audio is playing the UIButton is set to selected.
I would like "Button3" to implement multiple functions in a row.
That means when I press "Button 3", "player 3" should be played first, after that "player 1" and after that "player 2".
However, when I press "Button3", "player 1" and "player 2" are played at same time as there is no delay for the previous to finish.
I found out setting the delegate of the AVAudioPlayer or using AVQueuePlayer would solve the problem, but I find it difficult to make changes.
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)
}
}
}
Changed code
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")
}
EDIT: This is the method for AVAudioPlayer
So basically:
1: Add only one player, remove the rest of the players.
2: Create an NSMutableArray with your objects that you want to play.
3: Depending on what button gets pressed, you can re-arrange the NSMutableArray objects to set the correct order as you wish. (Simply recreate the array if you want to make it easy) And start playing the firstObject (url) in the array adding it accordingly to your player.
4: When the player finished playing, you can start playing the next object adding it to your player from the NSMutableArray the same way as done above.
Following above steps will avoid having multiple players playing simultaniously, together with other benefits (like avoid loading multiple URLs at the same time etc)
You may need some variable to check the currentPlayingObject to determine which one is next, maybe an int, and check that you don't try to load a new item from the array if it is the last item playing, to avoid crash on accessing objectAtIndex that does not exist.