3
votes

So I have been trying to use the MusicKit APIs for a few days now. I have been attempting to use the MPMusicPlayerApplicationController and MutableQueue APIs.

I have queue initialized already using setQueue(with: [String]) with an array of store identifiers for Apple Music songs. Then I want to allow the user to reorder the songs in the queue. I use the following code to attempt that.

let musicPlayerController = MPMusicPlayerController.applicationQueuePlayer

musicPlayerController.perform(queueTransaction: { queue in 

  let afterItem = queue.items.first(where: { $0.playbackStoreID == predecessorId })
  let descriptor = MPMusicPlayerStoreQueueDescriptor(storeIDs: [newItemId])
  queue.insert(descriptor, after: afterItem)

}) { (queue, error) in

  // Completion for when items' position update
  if error != nil {
    print(error!)
  }
}

The code above works as expected if afterItem is nil (i.e. the song is correctly inserted at the front of the queue). However, if afterItem is not nil, nothing happens. The queue stays the exact same as if no insert happened and there is no error provided in the completion handler. This problem happens regardless of whether the song being inserted is already in the queue or not.

Am I attempting modifying the queue incorrectly?

1
So if you log the queue before and after, it stays the same? I'm just curious how we know that "nothing happens". I'm not doubting you (this whole API is horribly buggy), just curious. - matt
@matt yes, when logging the queue it is the same - Nick
@matt I just checked again to verify. The all the media items are the same before and after and the order is the same. Some of the media items in the after queue are different objects then the before queue but they have the same contents (storeId, artist, title, etc.) The queues are also different objects. - Nick
Yep, I can confirm this. It's a clear bug. Not just Apple Music; it's queue.insert no matter what kind the songs are. Please do file a bug report on this. - matt
A further bug is that even if insert is nil, the queue in the completion handler does not reflect the change in the queue. - matt

1 Answers

0
votes

Ok, I found the solution.

If you want the queue to be mutated.

You need to return the query

let musicPlayerController = MPMusicPlayerController.applicationQueuePlayer

musicPlayerController.perform(queueTransaction: { queue in 

  let afterItem = queue.items.first(where: { $0.playbackStoreID == predecessorId })
  let descriptor = MPMusicPlayerStoreQueueDescriptor(storeIDs: [newItemId])

  //return the modification here.
  return queue.insert(descriptor, after: afterItem)

}) { (queue, error) in

  // Completion for when items' position update
  if error != nil {
    print(error!)
  }
}