Ошибка: MPMediaItem Статус загрузки на iOS и MPMediaPropertyPredicate с использованием assetURL

Забавная ошибка в API MPMedia

У меня была постоянная ошибка в моем музыкальном приложении, которую я наконец-то отследил (теперь, когда я переписываю ее по-быстрому). У него есть несколько граней. (используя systemMusicPlayer)

  1. Я думаю, что я сузил проблемы до MPMediaItem, который имеет следующие свойства.
    • MPMediaItemPropertyIsCloudItem = true
    • assetURL = ноль
    • ** эти два имеют смысл, но следующий угловой случай (ну, вероятно, довольно распространенный) бросил меня на некоторое время **
    • Первые 2 элемента могут быть правдой, но я полагаю, что если вы скопировали его из iTunes, он / может / будет воспроизводиться (они будут играть большую часть времени для меня), и нет никакого способа узнать. Я проверял это снова и снова, и, похоже, это так, но эти MPMediaItems по своему существованию могут только иногда вызывать проблемы, или они в порядке. Но вы не можете узнать, какие это песни.
  2. Если вы играете в очередь, и systemMusicPlayer обнаруживает песню в вашей библиотеке, но не загруженную или скопированную из iTunes, я полагаю, что она автоматически пропустит песню, подобно systemMusicPlayer.skipToNextItem(), но я думаю, что внутренне это другой механизм.
    • 2а. Такое поведение вызывает в основном неисправимую проблему, если вы используете systemMusicPlayer.skipToPreviousItem() и сталкиваетесь с элементом, который был бы пропущен - это означает, что он не распознает, что вы пытаетесь вернуться назад в очередь, и просто выдает ошибку и перемещает очередь вперед.
    • 2b. Насколько я мог судить, когда ошибка переходит вперед, MPMediaItem никогда не становится nowPlayingItem. Проблемы, возникающие в обратном направлении, усугубляются загрузкой метаданных MPMediaItem (которые всегда доступны независимо от того, локальные они или нет), но песня, пытающаяся воспроизвести ее, немедленно отправляет ее в очередь снова.

ОК, так глупо и бесит.

Теперь на мой вопрос:

Я ничего не могу поделать с тем, что не могу узнать, есть ли облачный элемент на устройстве или нет (через iTunes). Я / должен / смог бы просто отфильтровать, если у элемента есть assetURL, что является гарантией того, что он локальный и доступен.

let filter:MPMediaPropertyPredicate = MPMediaPropertyPredicate(value: "ipod", forProperty: MPMediaItemPropertyAssetURL, comparisonType: MPMediaPredicateComparison.Contains)

Это возвращает 0 пунктов. Кто-нибудь знает способ фильтрации этого свойства? Делая это здесь, кажется, что это было бы самым чистым, и должно оставить запрос, возвращающий элементы и itemSections. Все мои таблицы заполнены запросами, и я не думаю, что есть способ восстановить один вручную.

URL-адрес имеет следующий формат: ipod-library://item/item.m4a? Id=5314739480586915369

Теперь я подозреваю, что можно добавлять защелки при заполнении табличных представлений и тому подобное, но это выглядит очень грязно.

Это ios 9.2.1, Swift 2, Xcode 7.2.1

Я еще не вытер телефон и переписал песни. Загрузка их вручную из приложения "Музыка" - это единственный способ, при котором элементы получают assetURL, если он отсутствует.

2 ответа

Это не так эффективно, но вы можете сделать одну вещь:

let query = MPMediaQuery()
let allItems = query.items ?? []
let items = allItems.filter { $0.assetURL?.scheme?.hasPrefix("ipod") ?? false }

Из MPMediaItem.h вы можете видеть, что только они являются фильтруемыми (комментируются с фильтруемыми):

MPMediaItemPropertyPersistentID
MPMediaItemPropertyMediaType
MPMediaItemPropertyTitle
MPMediaItemPropertyAlbumTitle
MPMediaItemPropertyAlbumPersistentID
MPMediaItemPropertyArtist
MPMediaItemPropertyArtistPersistentID
MPMediaItemPropertyAlbumArtist
MPMediaItemPropertyAlbumArtistPersistentID
MPMediaItemPropertyGenre
MPMediaItemPropertyGenrePersistentID
MPMediaItemPropertyCompose
MPMediaItemPropertyComposerPersistentID
MPMediaItemPropertyIsCompilation
MPMediaItemPropertyIsCloudItem
MPMediaItemPropertyHasProtectedAsset
MPMediaItemPropertyPodcastTitle
MPMediaItemPropertyPodcastPersistentID
MPMediaItemPropertyPlayCount

Поэтому невозможно построить любой запрос с условием для свойства assetURL. Это тупиковая попытка что-либо сделать на assetURL, если вы не извлекаете все MPMediaItems и не выполняете поиск NSArray.

Кроме того, откуда-то из документации Apple, я смутно помню, что вы никоим образом не можете получить информацию о том, где загружен облачный элемент или нет.

Однако, если вы хотите больше исследовать облачные / локальные проблемы, я предлагаю вам принять во внимание настройку музыки пользователя, если музыкальная библиотека iCloud включена или выключена, и посмотреть на MPMediaItemPropertyHasProtectedAsset.

Если цель состоит в том, чтобы определить, является ли песня локальной песней или нет, вы можете просто создать запрос для обоих isCloudItem == FALSE AND hasProtectedAsset == FALSE, в этом случае assetURL не имеет значения.

Другие вопросы по тегам