This code results in silence:
let query = MPMediaQuery.songs()
let result = query.items
guard let items = result, items.count > 0 else {return}
let song = items[0]
let player = MPMusicPlayerController.applicationQueuePlayer
let coll = MPMediaItemCollection(items: [song])
let q = MPMusicPlayerMediaItemQueueDescriptor(itemCollection: coll)
player.setQueue(with: q)
player.play()
I've stepped through the code, and we reach player.play()
. I have an MPMediaItem and I've correctly formed an MPMediaItemCollection from that, and an MPMusicPlayerMediaItemQueueDescriptor from that. So why isn't my player playing?
You've found a bug. It appears that the initializer MPMusicPlayerMediaItemQueueDescriptor(itemCollection:)
is completely broken: it results in an unusable queue descriptor.
The workaround, where possible, is to use the other initializer instead, namely MPMusicPlayerMediaItemQueueDescriptor(query:)
.
For example, in this case, you could write (picking up in the last four lines of the original code):
let coll = MPMediaItemCollection(items: [song])
let predicate = MPMediaPropertyPredicate(
value: song.persistentID,
forProperty: MPMediaItemPropertyPersistentID)
let query = MPMediaQuery(filterPredicates: [predicate])
let q = MPMusicPlayerMediaItemQueueDescriptor(query: query)
player.setQueue(with: q)
player.play()
Unfortunately, there are many circumstances where you can't form a single query that gets the MPMediaItemCollection you really wanted.
In this particular example you could work around that, too, by setting the player's queue directly with an MPMediaItemCollection instead of a MPMusicPlayerMediaItemQueueDescriptor made from an MPMediaItemCollection.
But alas, there are some commands (such as append(_:)
) that require an MPMusicPlayerMediaItemQueueDescriptor, and for things like that, this entire API is basically hosed. It has been hosed since iOS 10.1 and it remains hosed in iOS 11.1.
"It has been hosed since iOS 10.1 and it remains hosed in iOS 11.1." Seconded.
I have been in the midst of a protracted fight just trying to a) get MPMusicPlayerController to simply work (finally managed that) and b) get it to play a song from an offset (still have not). And this is in an app that prior to iOS 10 worked 100% as expected.
Right now, this is code that works for me (at least with regard to getting a song to play):
let currentPlayer = MPMusicPlayerController.applicationQueuePlayer()
currentPlayer.repeatMode = .none
self.currentCollection = MPMediaItemCollection(items: [mediaItem])
currentPlayer.beginGeneratingPlaybackNotifications()
let query = MPMediaQuery.songs()
let pred = MPMediaPropertyPredicate(value: mediaItem.persistentID, forProperty: MPMediaItemPropertyPersistentID)
query.addFilterPredicate(pred)
let desc = MPMusicPlayerMediaItemQueueDescriptor(query: query)
currentPlayer.setQueueWith(desc)
currentPlayer.prepareToPlay(completionHandler: {[unowned self] (error) in
MPMusicPlayerController.applicationQueuePlayer().play()
})
It is a bit convoluted in that I had to use what I would consider the most complicated means based on available APIs. But several other methods cause the completion block to either never get called or get a completely unhelpful error. Right now I have 5 bugs reported to Apple with regard to MPMusicPlayerController so I am not exactly a happy developer at the moment. I will be opening one more related to this code as setStartTime & setEndTime does not appear to work any better than currentPlaybackTime for starting play at a specified offset.
This code does dependably play synced and downloaded Apple Music items though.
来源:https://stackoverflow.com/questions/46836728/cant-set-mpmusicplayercontroller-queue-with-mpmusicplayermediaitemqueuedescript