Ошибка: MPMediaItem Статус загрузки на iOS и MPMediaPropertyPredicate с использованием assetURL
Забавная ошибка в API MPMedia
У меня была постоянная ошибка в моем музыкальном приложении, которую я наконец-то отследил (теперь, когда я переписываю ее по-быстрому). У него есть несколько граней. (используя systemMusicPlayer)
- Я думаю, что я сузил проблемы до MPMediaItem, который имеет следующие свойства.
- MPMediaItemPropertyIsCloudItem = true
- assetURL = ноль
- ** эти два имеют смысл, но следующий угловой случай (ну, вероятно, довольно распространенный) бросил меня на некоторое время **
- Первые 2 элемента могут быть правдой, но я полагаю, что если вы скопировали его из iTunes, он / может / будет воспроизводиться (они будут играть большую часть времени для меня), и нет никакого способа узнать. Я проверял это снова и снова, и, похоже, это так, но эти MPMediaItems по своему существованию могут только иногда вызывать проблемы, или они в порядке. Но вы не можете узнать, какие это песни.
- Если вы играете в очередь, и 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 не имеет значения.