2012-11-12 51 views
9

如何搜索iPod的图书馆以同样的方式作为的iOS音乐应用程序?我想进行一般查询,返回每个艺术家,专辑和歌曲的结果。例如,如果我搜索Kenny Chesney,我希望歌曲查询返回所有Kenny Chesney歌曲(以及任何包含Kenny Chesney的歌曲标题或专辑)。当我为每个属性(歌曲标题,专辑标题,艺术家姓名),返回一个空数组。MPMediaQuery搜索艺术家,专辑和歌曲

下面是一些代码,可能会给你什么,我试图完成一个更好的想法:

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]); 

我必须通过运行单独的每个谓词查询这方面的工作,但是这似乎很效率低下!

回答

14

结合谓词这种方式使得它像“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 */ 
} 
+0

只是提到他,如果你做3个分别查询,你可以用重复的项目结束了。例如。如果专辑被命名为艺术家等 – 2013-02-06 18:03:35

+0

@relikd是的,这是我的地方。我有三个不同的查询添加到三个数组 - 但有重复的 - 这显然是一个问题。 – daidai

+0

你可以在将它们与'if([arr indexOfObject:song] == NSNotFound){[arr addObject:song]; }'。但是这并不是非常有效,特别是在大型阵列上。这是因为在添加新项目之前,indexOfObject:向所有项目发送了一个isEqual:消息。 – 2013-02-07 14:03:57

8

这个工作对我来说:

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]; 
} 

我基本上后过滤越来越来自媒体查询的所有项目。我不认为我的解决方案比首先过滤查询更好,但绝对比单独搜索三次更好。或者多次遍历数组。

+0

如何将结果分组到“MPMediaItemCollection”中,以便不返回属于3个专辑的50首歌曲,而只返回3个专辑? – sooper

+0

你的意思是一个有3个专辑的数组,每个专辑包含曲目?或者你的意思是每张专辑的一个随机项目? – 2013-06-07 14:56:07

+0

第二个,但是也想第一个的意见。我发现要做的唯一方法是循环访问过滤的数组,并删除重复的'MPMediaItemPropertyAlbumPersistentID'。虽然我喜欢你的方法,但我发现它很贵,虽然听起来有些乏味,但为艺术家,标题和专辑标题制作单独的“MPMediaQuery”,并将过滤后的项目合并到一个阵列中对于我来说(对于4000+以上的音乐库)的处理速度更快。 – sooper

2

这里有两种方法:获得使用一切查询

  1. 使用多个MPMediaPropertyPredicates。使用这种方法,您需要执行多个查询并自行汇总结果。 NSSet是你的朋友!

  2. 获取一切(或接近)从库,然后做之后,你的搜索或过滤。

在较早的设备或操作系统版本上,访问音乐库的速度会非常慢。根据我自己的经验,实现与您所描述的内容非常相似的事情,我用方法2得到了最好的结果。一旦我有了,那么我就使用分散/收集方法对这些项目进行迭代(我的需求不允许为此使用NSPredicate)。实际上,对于我来说,这比方法1更具性能,但我知道在iOS 6中,差距已经有所收敛。

相关问题