I read through many similar questions on stackoverflow, and while they helped, I still can't get the next song to play automatically when the one that's currently playing finishes. Since I start the array of songs at position 0, when I increment this position variable, shouldn't all the songs play, one after another, until I get to the last song in the array? Currently, after the first song finishes playing, the second song plays, the rest do not. So my code can only play two songs at a time, one after the other. I set up the songs initially inside the configureUI() method and I try to increment the songs in the AVAudioplayer delegate method at the bottom. I appreciate any insight.
//
// PLayerViewController.swift
// Maanso
//
//
import UIKit
import AVFoundation
class PLayerViewController: UIViewController, AVAudioPlayerDelegate {
@IBOutlet var holder: UIView!
var Git = UILabel()
var gabayArray = [Gabays]()
var currentIndex = 0
var position: Int = 0
var player: AVAudioPlayer?
//user interface elements
var coverImageView: UIImageView!
var gabayName: UILabel!
var gabyaaName: UILabel!
//buttons
var playPauseButton: UIButton!
var backButton: UIButton!
var forwardButton: UIButton!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
configure()
player!.delegate = self
// configureUI()
}
override func viewWillAppear(_ animated: Bool) {
if let player = player {
// player.play()
player.prepareToPlay()
}
}
override func viewDidLayoutSubviews() {
if holder.subviews.count == 0 {
configure()
}
}
func configure() {
//set up player
let gabay = gabayArray[position]
// let urlString = Bundle.main.path(forResource: gabay.gabayName, ofType: "mp3")
let urlString = Bundle.main.path(forResource: gabay.gabayName, ofType: "mp3")
do {
try AVAudioSession.sharedInstance().setMode(.default)
try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
guard let urlString = urlString else{return}
player = try AVAudioPlayer(contentsOf: URL(string: urlString)!)
guard let player = player else{return}
player.volume = 0.5
player.play()
}
catch{
print("error is: \(error.localizedDescription)")
}
configureUI()
}
//MARK: - actions
@objc func volumeSliderChanged(_ slider: UISlider) {
let value = slider.value
//adjust player volume
guard let player = player else{return}
player.volume = value
}
@objc func playPauseButtonTapped(_ slider: UISlider) {
guard let player = player else{return}
if player.isPlaying {
player.stop()
playPauseButton.setBackgroundImage(UIImage(systemName: "play.fill"), for: .normal)
}else{
player.play()
playPauseButton.setBackgroundImage(UIImage(systemName: "pause.fill"), for: .normal)
}
}
@objc func backButtonTapped() {
if position > 0
{
position = position - 1
player!.stop()
for subview in holder.subviews {
subview.removeFromSuperview()
}
configure()
// configureUI()
}
}
@objc func forwardButtonTapped() {
if position < gabayArray.count - 1{
position = position + 1
player!.stop()
for subview in holder.subviews {
subview.removeFromSuperview()
}
configure()
// configureUI()
}
}
@objc func seekSliderChanged(_ slider: UISlider) {
let slider = slider
// let currentTime = player!.currentTime
let duration = player!.duration
slider.maximumValue = Float(duration)
let time = duration/duration
//seeking through current gabay
player!.currentTime = TimeInterval(slider.value)
// player!.play()
Timer.scheduledTimer(withTimeInterval: Double(time), repeats: true, block: {
_ in
slider.value = Float(self.player!.currentTime)
//TRYING TO MAKE THE SLIDER BE IN SYNC WITH song
})
}
public func configureUI() {
//set up user interface
let gabay = gabayArray[position]
//set up imagecoverview
coverImageView = UIImageView()
coverImageView.contentMode = .scaleAspectFill
coverImageView.image = UIImage(named: gabay.imageName)
coverImageView.translatesAutoresizingMaskIntoConstraints = false
holder.addSubview(coverImageView)
//set up the two labels
gabayName = UILabel()
gabayName.textAlignment = .center
gabayName.numberOfLines = 0
gabayName.translatesAutoresizingMaskIntoConstraints = false
gabayName.text = gabay.gabayName
gabayName.font = UIFont(name: "helvetica", size: 20)
holder.addSubview(gabayName)
gabyaaName = UILabel()
gabyaaName.translatesAutoresizingMaskIntoConstraints = false
gabyaaName.text = gabay.gabyaaName
gabyaaName.font = UIFont(name: "helvetica", size: 18)
gabyaaName.textAlignment = .center
gabyaaName.numberOfLines = 0
holder.addSubview(gabyaaName)
//set up sliders.
let volumeSlider = UISlider()
volumeSlider.value = 0.5
volumeSlider.translatesAutoresizingMaskIntoConstraints = false
volumeSlider.addTarget(self, action: #selector(volumeSliderChanged), for: .valueChanged)
volumeSlider.layer.cornerRadius = 8
volumeSlider.isUserInteractionEnabled = true
holder.addSubview(volumeSlider)
//seek through sider
let seekSlider = UISlider()
// seekSlider.isContinuous = true
seekSlider.minimumValue = 0
// seekSlider.maximumValue = Float(player!.duration)
seekSlider.isUserInteractionEnabled = true
seekSlider.translatesAutoresizingMaskIntoConstraints = false
// seekSlider.setThumbImage(UIImage(systemName: "thumbSmall"), for: .normal)
seekSlider.setThumbImage(UIImage(named: "thumb"), for: .normal)
seekSlider.addTarget(self, action: #selector(seekSliderChanged), for: .valueChanged)
holder.addSubview(seekSlider)
//set up buttons, play button
playPauseButton = UIButton()
playPauseButton.tintColor = .black
playPauseButton.setBackgroundImage(UIImage(systemName: "pause.fill"), for: .normal)
playPauseButton.translatesAutoresizingMaskIntoConstraints = false
playPauseButton.addTarget(self, action: #selector(playPauseButtonTapped), for: .touchUpInside)
holder.addSubview(playPauseButton)
//back button
backButton = UIButton()
backButton.tintColor = .black
backButton.setBackgroundImage(UIImage(systemName: "backward.fill"), for: .normal)
backButton.translatesAutoresizingMaskIntoConstraints = false
backButton.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside)
holder.addSubview(backButton)
//forward button
forwardButton = UIButton()
forwardButton.tintColor = .black
forwardButton.setBackgroundImage(UIImage(systemName: "forward.fill"), for: .normal)
forwardButton.translatesAutoresizingMaskIntoConstraints = false
forwardButton.addTarget(self, action: #selector(forwardButtonTapped), for: .touchUpInside)
holder.addSubview(forwardButton)
//volume buttons
let rightVolButton = UIButton()
rightVolButton.translatesAutoresizingMaskIntoConstraints = false
rightVolButton.setBackgroundImage(UIImage(systemName: "volume.3.fill"), for: .normal)
holder.addSubview(rightVolButton)
//set up constraints
NSLayoutConstraint.activate([
coverImageView.topAnchor.constraint(equalTo: holder.layoutMarginsGuide.topAnchor, constant: 80),
coverImageView.leadingAnchor.constraint(equalTo: holder.layoutMarginsGuide.leadingAnchor, constant: 0),
coverImageView.trailingAnchor.constraint(equalTo: holder.layoutMarginsGuide.trailingAnchor, constant: 0),
gabayName.topAnchor.constraint(equalTo: coverImageView.bottomAnchor, constant: 100),
gabayName.centerXAnchor.constraint(equalTo: holder.centerXAnchor),
gabyaaName.topAnchor.constraint(equalTo: gabayName.bottomAnchor, constant: 15),
gabyaaName.centerXAnchor.constraint(equalTo: holder.centerXAnchor),
//seek slider
seekSlider.topAnchor.constraint(equalTo: gabyaaName.topAnchor, constant: 30),
seekSlider.centerXAnchor.constraint(equalTo: holder.centerXAnchor),
seekSlider.widthAnchor.constraint(equalTo: holder.widthAnchor, multiplier: 0.8),
//buttons
playPauseButton.topAnchor.constraint(equalTo: seekSlider.bottomAnchor, constant: 25),
playPauseButton.centerXAnchor.constraint(equalTo: holder.centerXAnchor),
playPauseButton.widthAnchor.constraint(equalToConstant: 70),
playPauseButton.heightAnchor.constraint(equalToConstant: 70),
backButton.topAnchor.constraint(equalTo: seekSlider.bottomAnchor, constant: 25),
backButton.leadingAnchor.constraint(equalTo: holder.leadingAnchor, constant: 20),
backButton.widthAnchor.constraint(equalToConstant: 70),
backButton.heightAnchor.constraint(equalToConstant: 70),
forwardButton.topAnchor.constraint(equalTo: seekSlider.bottomAnchor, constant: 25),
forwardButton.trailingAnchor.constraint(equalTo: holder.trailingAnchor, constant: -20),
forwardButton.widthAnchor.constraint(equalToConstant: 70),
forwardButton.heightAnchor.constraint(equalToConstant: 70),
//volume slider
volumeSlider.topAnchor.constraint(equalTo: playPauseButton.bottomAnchor, constant: 30),
volumeSlider.centerXAnchor.constraint(equalTo: holder.centerXAnchor),
volumeSlider.widthAnchor.constraint(equalTo: holder.widthAnchor, multiplier: 0.8),
rightVolButton.topAnchor.constraint(equalTo: playPauseButton.bottomAnchor, constant: 35),
rightVolButton.trailingAnchor.constraint(equalTo: holder.layoutMarginsGuide.trailingAnchor, constant: 0),
])
}
//MARK: - AVAudioplayer delegate
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
if flag, position < gabayArray.count - 1 {
position = position + 1
for subview in holder.subviews{
subview.removeFromSuperview()
}
configure()
}
}
override func viewWillDisappear(_ animated: Bool) {
player?.stop()
}
}