Swift AVAudioPlayer is not stoping the song and button not disappeared on leave UITable View

Viewed 75

I have been struggling with 2 issues for the last 2 weeks and couldn't find the solution yet, working on an audio player where I want to play the audio files when the UItableview cell clicked or the button inside clicks on the play button So I created a struct with Audio details which I later plan to extract from mp3 files like song name, artist duration, etc. but right now I hard code these details so that my main focus is to play a song on cell tap or button

struct Audio {
    let id: Int
    let trackName: String
    let trackTitle: String
    let creationDate = Date()
    let album: String
    let uploadedBy: String
    let genre: String
    let lyricsLang: String
    let artist: String
    let duration: Float
    var completed = false
 }

Problems

  1. I want to hide the play button if the user clicks the other cell only that cell which is playing the current song will show the button (it's for either play or stop) but the problem are buttons shows on each row of the cell also I don't want to hide the button if I click the playing song cell again.

  2. If the user taps on cell, based on cell number it'll always play the same song and I want to play songs like 0.mp3, 1.mp3, 2.mp3, 3.mp3 based on what is the cell number, and the stop button is not working if I tried to stop the song before I play the next song or tried to leave the cell Below is my whole code

     class AudioListViewController: UIViewController {
          var selectedRowIndex = -1
          var songList: [Audio] = [
          Audio(id: 0, trackName: "Song 1", trackTitle: "ABbcd:", album: "Loreim loreim", 
             uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God", 
             duration: 2.00),
          Audio(id: 1, trackName: "Song 2", trackTitle: "ABbcd:", album: "Loreim loreim", 
             uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God", 
             duration: 2.00),
          Audio(id: 2, trackName: "Song 3", trackTitle: "ABbcd:", album: "Loreim loreim", 
             uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God", 
             duration: 2.00)
          ]            
          @IBOutlet weak var songListTableView: UITableView!
          var isTapped: Bool = false
          @IBOutlet weak var close: UIButton!
    
          override func viewDidLoad() {
              super.viewDidLoad()
    
              songListTableView.dataSource = self
              songListTableView.delegate = self
              title = "Back"
              navigationItem.backButtonTitle = "Back be?"
    
              songListTableView.register(UINib(nibName:  "SongsListTableViewCell", bundle: 
             nil), 
             forCellReuseIdentifier: "SongListCell")
         }
    
         @IBAction func closeSe(_ sender: Any) {
              self.dismiss(animated: true, completion: nil)
         }
    
      }
      extension AudioListViewController: UITableViewDataSource {
            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> 
            Int {
                 return songList.count
             }
    
             func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 
               UITableViewCell {
                  let cell = tableView.dequeueReusableCell(withIdentifier: "SongListCell", 
                  for: indexPath) as! SongsListTableViewCell
    
             cell.songTitle?.text = songList[indexPath.row].trackName
             cell.songDuration?.text = String(songList[indexPath.row].duration)
             return cell
          }
        }
    
        extension AudioListViewController: UITableViewDelegate{
             func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                  tableView.deselectRow(at: indexPath, animated: true)
                  let position = indexPath.row
    
                  print(indexPath.row)
                  let vc = tableView.dequeueReusableCell(withIdentifier: "SongListCell", for: 
          indexPath)
             as! SongsListTableViewCell
    
         vc.songs = songList
         vc.position = position
    
         let selectedFilterRow = songList[indexPath.section].id
         if selectedFilterRow == indexPath.row {
            return
         }
    
         if let previousCell = tableView.cellForRow(at: IndexPath(row: selectedFilterRow, 
           section: indexPath.section)) {
               vc.useSong.isHidden = true
               vc.useSong.alpha = 0
               vc.stopSong()
         }
    
         if let cell = tableView.cellForRow(at: indexPath) {
               vc.useSong.isHidden = true
               vc.useSong.alpha = 0
               vc.stopSong()
               vc.configure(position: position)
          }
         }
       }
    

Now to get the song file name on tap, and other feature of cell

     class SongsListTableViewCell: UITableViewCell {

        public var songs: [Audio] = [
            Audio(id: 0, trackName: "Song 1", trackTitle: "ABbcd:", album: "Loreim loreim", 
               uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God", 
               duration: 2.00),
            Audio(id: 1, trackName: "Song 2", trackTitle: "ABbcd:", album: "Loreim loreim", 
               uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: "God", 
               duration: 2.00),
            Audio(id: 2, trackName: "Song 3", trackTitle: "ABbcd:", album: "Loreim loreim", 
               uploadedBy: "A men", genre: "Romantic", lyricsLang: "English", artist: 
               "God", duration: 2.00) ]

            public var position: Int = 0
            public var isPlaying: Bool = false
            var cellsState: Bool = false
            var songPlayer: AVAudioPlayer?

            @IBOutlet weak var singleViewCell: UIStackView!
            @IBOutlet weak var songCellView: UIView!
            @IBOutlet weak var songImage: UIImageView!
            @IBOutlet weak var songTitle: UILabel!
            @IBOutlet weak var songDuration: UILabel!
            @IBOutlet weak var makeFavorite: UIButton!
            @IBOutlet weak var useSong: UIButton!

            let songReoad: AudioListViewController! = nil

            override func awakeFromNib() {
               super.awakeFromNib()
               useSong.addTarget(self, action: 
                 #selector(SongsListTableViewCell.selectSong(_:)), for: .touchUpInside)
               makeFavorite.addTarget(self, action: 
                 #selector(SongsListTableViewCell.makeFavourite(_:)), for: .touchUpInside )
                useSong.isHidden = true
           }

           private let albumNameLabel: UILabel = {
               let label = UILabel()
               label.textAlignment = .center
               label.numberOfLines = 0 // line wrap
               return label
           }()

           private let artistNameLabel: UILabel = {
               let label = UILabel()
               label.textAlignment = .center
               label.numberOfLines = 0 // line wrap
               return label
           }()
           override func setSelected(_ selected: Bool, animated: Bool) {
               super.setSelected(selected, animated: animated)
               useSong.layer.cornerRadius = 6
               configure(position: self.position)
           }

           func configure(position:Int) {
  
              let song = songs[position]  
              let songId = String(song.id)
              let urlString = Bundle.main.path(forResource: songId, ofType: "mp3")
    
  
              do {
                 try AVAudioSession.sharedInstance().setMode(.default)
                 try AVAudioSession.sharedInstance().setActive(true, options: 
                   .notifyOthersOnDeactivation)
                 guard let urlString = urlString else {
                    return
                 }

                 songPlayer = try AVAudioPlayer(contentsOf: URL(string: urlString)!)
                 guard let player = songPlayer else {
                    return
                 }
                 player.volume = 0.5

                 player.play()
                 isPlaying = true
             }
              catch {
                  print("error occurred")
             }

             songTitle.text = song.trackName
             albumNameLabel.text = song.album

            
              // Frame
              let yPosition = artistNameLabel.frame.origin.y + 70 + 20
              let size: CGFloat = 70

               backButton.frame = CGRect(x: 20,
                              y: yPosition,
                              width: size,
                              height: size)

               // Add actions
               makeFavorite.addTarget(self, action: #selector(didTapPlayPauseButton), for: 
                 .touchUpInside)
               
           }

           func stopSong(){
              if let player = songPlayer {
                 player.stop()
              }else{
                 songPlayer?.stop()
              }
           }

           @IBAction func selectSong(_ sender: UIButton) {
                cellsState = !cellsState
                songPlayer?.stop()
                if (cellsState) {
                    useSong.isHidden = false
                    useSong.alpha = 1
                    UIView.animate(withDuration: 0.6,
                       animations: {
                           self.useSong.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
                     },
                     completion: { _ in
                         UIView.animate(withDuration: 0.6) {
                            self.useSong.transform = CGAffineTransform.identity
                      }
                  })
               } else {
                    useSong.isHidden = true
                    useSong.alpha = 0
             }
         }

          @IBAction func makeFavourite(_ sender: UIButton) {
              sender.isSelected = !sender.isSelected
              if sender.isSelected {
                  makeFavorite.setImage(UIImage(systemName: "star.fill"), for: .normal)
              } else {
                   makeFavorite.setImage(UIImage(systemName: "star"), for: .normal)
              }
           }

 
           @objc func didTapPlayPauseButton() {
                if songPlayer?.isPlaying == true {
                   // pause
                   songPlayer?.pause()
                }
                else {
                   // play
                  songPlayer?.play()
                }
             }
       }

This is how it's looking right now SongList view

This is my Songlistview songlistview

0 Answers
Related