3

I am using an instance of MPMusicPlayerController.systemMusicPlayer to enqueue an array of store IDs. This has worked for months now. Earlier today I updated to iOS 14.3, and the player is now failing to play songs.

The code below is the minimal amount needed to replicate the bug:

// note: repo using any play method you want
let player = MPMusicPlayerController.systemMusicPlayer
let descriptor: MPMusicPlayerStoreQueueDescriptor?

func setup() {
 let storeIDs: [String] = ["lorem", "ipsum"] // fetch real IDs from the API
 descriptor = MPMusicPlayerStoreQueueDescriptor(queue: storeIDs)
}

func play() {
 self.player.setQueue(with: descriptor!)
 self.player.play()
}

// Expected: plays song with store ID "lorem"
// Actual: app freezes and I see error logs

When I play a song, instead of playing it, the app completely freezes (meaning it doesn't respond to user interaction), and I see the following logs:

[SDKPlayback] ASYNC-WATCHDOG-1: Attempting to wake up the remote process
[SDKPlayback] SYNC-WATCHDOG-1: Attempting to wake up the remote process
[SDKPlayback] ASYNC-WATCHDOG-2: Tearing down connection
[SDKPlayback] SYNC-WATCHDOG-2: Tearing down connection

The MPMusicPlayerController plays music just fine on iOS 14.2.

Can anybody confirm or shed some light on what's going on here?

I filed a TSI/bug report with Apple in the meantime.

Harman
  • 346
  • 2
  • 6
  • 1
    I can at least confirm that this problem exists and I am currently trying to resolve it myself in my app. If I find a solution I will let you know. – Amber Star Dec 18 '20 at 13:10
  • 1
    Seeing this on iOS 14.2 at `player.append()` after `player.setQueue(with:)`. Adding a `player.prepareToPlay()` in-between the statements stopped the freezes in my case. – Rolleric Jan 12 '21 at 18:38

1 Answers1

4

I can confirm the issue is still present, but after doing some testing I found out that what it's actually doing is blocking the main thread from executing. So a workaround that at least worked for me is executing the play function inside the background thread like this:

DispatchQueue.global(qos: .background).async {
player.prepareToPlay()
player.play()
}

Now the issue may still be present sometimes but i found that moving it to the background thread makes it way less tedious and less often. Also adding prepare to play also seems to make it work 99% of the time.

Alec Attie
  • 41
  • 3
  • yup, this helped me too. Although, I'd suggest using your own serial queue instead because the MPMusicPlayerController started giving me EXC_BAD_ACCESS failures on concurrent background threads. The docs note that we should use the main thread for MPMusicPlayerController, but I found a private serial queue works just as fine. I use something like `DispatchQueue(label: 'com.example.myqueue')` – Harman Mar 05 '21 at 02:38
  • 1
    This is effective for not freezing the UI, but I still get the issue and it delays actual start of music playback. – Germán Apr 25 '21 at 00:17