Сортировать альбомы по исполнителю, используя MPMediaQuery
Я пытаюсь получить доступ к локальной музыкальной библиотеке пользователя с помощью MPMediaQuery
отсортировать результаты следующим образом:
Artist A (sorted alphabetically) > All of Artist A's albums, sorted alphabetically
Artist B (sorted alphabetically) > All of Artist B's albums, sorted alphabetically
Artist C (sorted alphabetically) > All of Artist C's albums, sorted alphabetically
...
Мой запрос структурирован так:
MPMediaQuery *albumsQuery = [MPMediaQuery albumsQuery];
albumsQuery.groupingType = MPMediaGroupingAlbumArtist;
Но проблема в том, что, хотя вышеупомянутое в основном работает, возвращается только первый альбом на каждого исполнителя. То есть возвращается только один из альбомов Alt-J, а не два, которые существуют в библиотеке.
Это почему? И как я могу структурировать свой запрос, чтобы получить желаемый результат?
РЕДАКТИРОВАТЬ: Вот как я получаю доступ к альбомам. Запрос:
AlbumCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellID forIndexPath:indexPath];
MPMediaItemCollection *collection = [_items objectAtIndex:indexPath.row];
MPMediaItem *cellItem = [collection representativeItem];
куда _items
NSArray, который содержит MPMediaQuery
результат.
3 ответа
Кажется, что алгоритм Дэвида Барского очень медленный с большими библиотеками. Я выбрал другой подход:
-(NSArray *)albumsSortedByArtist
{
CFTimeInterval start = CACurrentMediaTime();
MPMediaQuery *albumsQuery = [MPMediaQuery albumsQuery];
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:@"representativeItem"
ascending:YES comparator:^NSComparisonResult(MPMediaItem * _Nonnull album1, MPMediaItem * _Nonnull album2) {
NSString *album1Name = [album1 valueForProperty:MPMediaItemPropertyAlbumArtist];
NSString *album2Name = [album2 valueForProperty:MPMediaItemPropertyAlbumArtist];
if (!album1Name || !album2Name) {
album1Name = [album1 valueForProperty:MPMediaItemPropertyArtist];
album2Name = [album2 valueForProperty:MPMediaItemPropertyArtist];
}
return [album1Name localizedStandardCompare:album2Name];
}];
NSArray *allAlbums = [albumsQuery.collections sortedArrayUsingDescriptors:@[sorter]];
NSLog(@"It took %f", CACurrentMediaTime() - start);
return allAlbums;
}
Это намного быстрее. В библиотеке iPhone 6 с 1161 альбомом:
2016-06-07 20:28:51.620 Musica[1205:515625] Mine: 0.394556
2016-06-07 20:29:20.528 Musica[1205:515625] David Barsky's: 28.906980
Как вы получаете доступ к альбомам из запроса? Есть метод items или, если я правильно помню, метод collection. Они немного отличаются в том, как они дают вам данные.
Очевидно, что вы можете сделать все вручную, просто получить список всех альбомов и отсортировать их самостоятельно!
РЕДАКТИРОВАТЬ I: группировка по исполнителю альбома означает, что коллекция дает вам каждого исполнителя альбома, а затем получение репрезентативного элемента - это всего лишь один альбом. Так что вам нужно сделать еще один запрос к коллекции, чтобы получить каждый альбом для этого исполнителя
РЕДАКТИРОВАТЬ II: Вы можете использовать то, что вы уже нашли, чтобы делать дополнительные запросы, так что, например, то, что вы уже получили, это коллекция всех разных исполнителей альбомов. Вы хотите знать, что представляют собой альбомы каждого исполнителя, чтобы вы могли повторить запрос с дополнительным предикатом:
MPMediaItem * albumArtist; // ранее полученный MPMediaQuery* albumQuery = [MPMediaQuery albumQuery]; MPMediaPropertyPredicate* albumPredicate = [MPMediaPropertyPredicate finalateWithValue: [albumArtist valueForProperty: MPMediaItemPropertyAlbumArtist] forProperty: MPMediaItemPropertyAlbumArtist]; [albumQuery addFilterPredicate: albumPredicate]; NSArray* allAlbums = [albumQuery collection];
Следующие работы (медленно, на прилично большой музыкальной библиотеке. Ваши результаты могут отличаться). Кредит идет в CMash за помощь.
- (NSArray *)queryForMusic {
NSMutableArray *allAlbums = [[NSMutableArray alloc] init];
MPMediaQuery *artistsQuery = [MPMediaQuery artistsQuery];
artistsQuery.groupingType = MPMediaGroupingAlbumArtist;
NSArray *allArtists = [artistsQuery collections];
for (MPMediaItemCollection *collection in allArtists) {
MPMediaItem *albumArtist = [collection representativeItem];
MPMediaQuery *albumQuery = [MPMediaQuery albumsQuery];
MPMediaPropertyPredicate* albumPredicate = [MPMediaPropertyPredicate predicateWithValue: [albumArtist valueForProperty: MPMediaItemPropertyAlbumArtist] forProperty: MPMediaItemPropertyAlbumArtist];
[albumQuery addFilterPredicate: albumPredicate];
NSArray *artistsAblums = [albumQuery collections];
[allAlbums addObjectsFromArray:artistsAblums];
}
return allAlbums;
}