MPMusicPlayerController.systemMusicPlayer setQueue difficulties

I am having difficulty with my music app. I have posted on SO and Reddit numerous times.



The goal of the app is to play music and when you land on a song you like tap a button and play more songs from the artist that is currently playing. When I am IN the app and I hit next song it works fine. However if I let the song end naturally the app would play a random song. So I added logic to say if the songs remaining time is 0 then play next song using media players func because I know that works. This solved it except if the app is in the background. I tried to keep the app alive if it is in the background but I guess that is not working.



Every time I think I have solved something it the issue comes back.


**What I expect to happen** is lock on an Artist, close app to background and when the song ends play another song from Artist.



**What actually happens** is when I lock the artist and close app to background is the song will end and sometimes it will play the right song. Sometimes it will not. **HOWEVER** when it plays the wrong song and I open the app back up it ends the currently (Wrong) playing song and starts playing a song by the proper artist



I have set the Capabilities to background fetch and Audio Airplay and picture in picture



I have tried to only post relevant code in order..



I have a property



let mediaPlayer = MPMusicPlayerController.systemMusicPlayer

var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid



In my **ViewDidLoad**



try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)

try? AVAudioSession.sharedInstance().setActive(true)



DispatchQueue.main.async {

self.clearSongInfo()

MediaManager.shared.getAllSongs { (songs) in

guard let theSongs = songs else {

return

}

self.mediaPlayer.nowPlayingItem = nil

self.newSongs = theSongs.filter({ (item) -> Bool in

return !MediaManager.shared.playedSongs.contains(item)

})

self.aSongIsInChamber = true

self.mediaPlayer.setQueue(with: MPMediaItemCollection(items: self.newSongs.shuffled())

)

self.mediaPlayer.shuffleMode = .off

self.mediaPlayer.repeatMode = .none

}

NotificationCenter.default.addObserver(self, selector: #selector(self.songChanged(_:)), name: NSNotification.Name.MPMusicPlayerControllerNowPlayingItemDidChange, object: self.mediaPlayer)

self.mediaPlayer.beginGeneratingPlaybackNotifications()

}



I have a func that updates the played time and remaining time and in that I have



if Int(self.songProgressSlider.maximumValue - self.songProgressSlider.value) < 1 {

print("song ended naturally, skipped")

mediaPlayer.prepareToPlay(completionHandler: { (error) in

DispatchQueue.main.async {

self.mediaPlayer.skipToNextItem()

}

})

}



When I play the music I have a bool **isPlaying**



If it is then the time is running and I have this



let app = UIApplication.shared

var task: UIBackgroundTaskIdentifier?

task = app.beginBackgroundTask {

app.endBackgroundTask(task!)

}



I have that to keep the timer on in the background so it will play the next song when the time remaining is 0





Now to lock onto an Artist I have the following code that executes on button tap



let artistPredicate: MPMediaPropertyPredicate = MPMediaPropertyPredicate(value: nowPlaying.artist, forProperty: MPMediaItemPropertyArtist)

let query: MPMediaQuery = MPMediaQuery.artists()

let musicPlayerController: MPMusicPlayerController = MPMusicPlayerController.systemMusicPlayer

query.addFilterPredicate(artistPredicate)

musicPlayerController.setQueue(with: query)