Can't set MPMusicPlayerController queue with MPMusicPlayerMediaItemQueueDescriptor

假如想象 提交于 2019-12-02 08:14:48

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!