MPMediaQuery搜索艺术家,专辑和歌曲

时间:2012-11-12 22:40:08

标签: iphone objective-c ios mpmediaitem mpmediaquery

如何以与iOS音乐应用程序相同的方式搜索iPod库?我想做一般查询,返回每个艺术家,专辑和歌曲的结果。例如,如果我搜索Kenny Chesney,我希望歌曲查询返回所有Kenny Chesney歌曲(以及包含Kenny Chesney的任何歌曲标题或专辑。)当我为每个属性(歌曲标题,专辑)创建此查询和谓词时标题,艺术家姓名),空数组返回。

这里有一些代码可以让您更好地了解我想要实现的目标:

MPMediaPropertyPredicate *songPredicate =
[MPMediaPropertyPredicate predicateWithValue:searchText
                                 forProperty:MPMediaItemPropertyTitle
                              comparisonType:MPMediaPredicateComparisonContains];

MPMediaPropertyPredicate *albumPredicate =
[MPMediaPropertyPredicate predicateWithValue:searchText
                                 forProperty:MPMediaItemPropertyAlbumTitle
                              comparisonType:MPMediaPredicateComparisonContains];

MPMediaPropertyPredicate *artistPredicate =
[MPMediaPropertyPredicate predicateWithValue:searchText
                                 forProperty:MPMediaItemPropertyArtist
                              comparisonType:MPMediaPredicateComparisonContains];

MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
[songsQuery addFilterPredicate:songNamePredicate];
[songsQuery addFilterPredicate:artistNamePredicate];
[songsQuery addFilterPredicate:albumNamePredicate];

NSLog(@"%@", [songsQuery items]);

我通过分别运行每个谓词的查询来实现这一点,但这看起来非常低效!

4 个答案:

答案 0 :(得分:15)

以这种方式组合谓词使其成为“AND”关系。这意味着您要查询的歌曲的标题,专辑和名称都与搜索文本相匹配。

要实现您要执行的操作,您应该运行3个查询并以正确的方式合并结果。

如果你跑:

MPMediaPropertyPredicate *artistPredicate =
[MPMediaPropertyPredicate predicateWithValue:searchText
                                 forProperty:MPMediaItemPropertyArtist
                              comparisonType:MPMediaPredicateComparisonContains];

NSSet *predicates = [NSSet setWithObjects: artistPredicate, nil];

MPMediaQuery *songsQuery =  [[MPMediaQuery alloc] initWithFilterPredicates: predicates];

NSLog(@"%@", [songsQuery items]);

这将使您与符合搜索条件的艺术家联系。 你应该为歌曲和专辑做同样的事情。

如果您这样做很慢,您可以立即检索所有媒体并手动过滤它:

MPMediaQuery *everything = [[MPMediaQuery alloc] init];

NSLog(@"Logging items from a generic query...");
NSArray *itemsFromGenericQuery = [everything items];
for (MPMediaItem *song in itemsFromGenericQuery) {
    NSString *songTitle = [song valueForProperty: MPMediaItemPropertyTitle];
    /* Filter found songs here manually */
}

答案 1 :(得分:11)

这对我有用:

MPMediaQuery *searchQuery = [[MPMediaQuery alloc] init];
NSPredicate *test = [NSPredicate predicateWithFormat:@"title contains[cd] %@ OR albumTitle contains[cd] %@ OR artist contains[cd] %@", searchString, searchString, searchString];
NSArray *filteredArray = [[searchQuery items] filteredArrayUsingPredicate:test];

//NSLog(@"%@", [filteredArray valueForKeyPath:@"title"]);

for (MPMediaItem *song in filteredArray) 
{
    [arrayOfSongItems addObject:song];
}

我基本上在获取媒体查询中的所有项目之后过滤。我不认为我的解决方案比首先过滤查询更好,但肯定比分别搜索三次更好。或者多次遍历数组。

答案 2 :(得分:2)

这里有两种方法:

  1. 使用多个MPMediaPropertyPredicates来使用查询获取所有内容。使用此方法,您将需要执行多个查询并自行汇总结果。 NSSet是你的朋友!

  2. 从库中获取所有内容(或接近它),然后在此之后进行搜索或过滤。

  3. 在较旧的设备或操作系统版本上访问音乐库的速度非常慢。根据我自己的经验,我实现了与你所描述的非常类似的东西,我用方法2得到了最好的结果。一旦我有了,那么几乎所有我然后使用分散/聚集方法迭代这些项目(我的需求不允许为此使用NSPredicate)。对于我来说,这实际上比方法1更高效,但我知道iOS 6的差距已经有所缩小。

答案 3 :(得分:0)

运行查询后用于过滤项目的Swift 3+解决方案,类似于Mohammed Habib's answer

let searchString = “string to search”
let query = MPMediaQuery()

let filteredItems = query.items?.filter { item -> Bool in
    let properties = [item.songTitle,
                      item.artist,
                      item.albumTitle]

    let lowercasedProperties = properties.compactMap { $0.lowercased() }

    return lowercasedProperties.contains(searchString.lowercased())
}

print(filteredItems ?? [])