2012-11-12 98 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中,差距已經有所收斂。

相關問題