更快的MPMediaItems的NSMutableArray? 代码审查

我有几周的时间进入iOS编程,还有很多需要学习的地方。 我有一种包含MPMediaItems的NSMutableArray工作,但是它有大约10秒的速度,有1200种物品,我正在寻找一种更快的方法。

我的最终目标是拥有一系列MPMediaItemCollection项目,每个项目代表一个专辑。 我不能从MPMediaQuery(据我所知)得到这个,因为我需要从播放列表中获取歌曲。 所以我正在对从特定播放列表(“过去4个月”)中获得的歌曲进行排序,然后构建我自己的集合数组。 正如我所说,下面的方法有效但速度很慢。 即使我只按MPMediaItemPropertyAlbumTitle排序,它仍然需要大约4秒钟(iPhone 4S)。

编辑:我应该提到我尝试排序描述符,但我无法获得工作的关键。 例如

NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"MPMediaItemPropertyAlbumTitle" ascending:YES]; 

这会返回错误

 [ valueForUndefinedKey:]: this class is not key value coding-compliant for the key MPMediaItemPropertyAlbumTitle. 

代码

 MPMediaQuery *query = [MPMediaQuery playlistsQuery]; NSArray *playlists = [query collections]; NSMutableArray *songArray = [[NSMutableArray alloc] init]; for (MPMediaItemCollection *playlist in playlists) { NSString *playlistName = ; NSLog (@"%@", playlistName); if ([playlistName isEqualToString:@"Last 4 months"]) { /* replaced this code with a mutable copy NSArray *songs = ; for (MPMediaItem *song in songs) { [songArray addObject:song]; } */ // the following replaces the above for-loop songArray = [ mutableCopy ]; [songArray sortUsingComparator:^NSComparisonResult(id a, id b) { NSString *first1 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumTitle]; NSString *second1 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumTitle]; NSString *first2 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumPersistentID]; NSString *second2 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumPersistentID]; NSString *first3 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumTrackNumber]; NSString *second3 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumTrackNumber]; NSString *first = [NSString stringWithFormat:@"%@%@%03d",first1,first2, [first3 intValue]]; NSString *second = [NSString stringWithFormat:@"%@%@%03d",second1,second2, [second3 intValue]]; return [first compare:second]; }]; } } 

我知道这是一个旧线程但我认为重要的是澄清为什么OPs排序代码不起作用,以便任何遇到此代码的人都不会放弃使用NSSortDescriptors。

代码:

 [[NSSortDescriptor alloc] initWithKey:@"MPMediaItemPropertyAlbumTitle" ascending:YES]; 

应该:

 [[NSSortDescriptor alloc] initWithKey:MPMediaItemPropertyAlbumTitle ascending:YES]; 

因为MPMediaItemPropertyAlbumTitle保存密钥的名称。

我多次使用过这段代码。

根据@cdelacroix的建议,我重新实现了我的比较块以级联三个排序键,只检查低位键,如果更高阶键是相同的。 这导致该类型的执行时间减少了50%以上。 尽管如此,它并不像我想的那么快,所以如果有人有更好的答案,请发布。

这是旧时代与新时代(1221项):

4S executionTime = 10.8,executionTime = 4.7

3GS executionTime = 21.6,executionTime = 9.3

有趣的是,从数组拷贝的for循环到mutableCopy的转换似乎并没有改善。 如果有的话,mutableCopy可能慢了十分之一(任何人都对mutableCopy进行了任何基准测试?)。 但我留下了改变,因为它看起来更干净。

最后,请注意检查专辑标题== nil。 请注意,比较认为任何具有零值的内容始终是NSOrderedSame。 列表中的一个专辑没有标题集,这搞砸了排序顺序而没有这个检查。

 MPMediaQuery *query = [MPMediaQuery playlistsQuery]; NSArray *playlists = [query collections]; NSMutableArray *songArray = [[NSMutableArray alloc] init]; for (MPMediaItemCollection *playlist in playlists) { NSString *playlistName = [playlist valueForProperty: MPMediaPlaylistPropertyName]; NSLog (@"%@", playlistName); if ([playlistName isEqualToString:@"Last 4 months"]) { songArray = [[playlist items] mutableCopy ]; [songArray sortUsingComparator:^NSComparisonResult(id a, id b) { NSComparisonResult compareResult; NSString *first1 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumTitle]; if(first1 == nil) first1 = @" "; // critical because compare will match nil to anything and result in NSOrderedSame NSString *second1 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumTitle]; if(second1 == nil) second1 = @" "; // critical because compare will match nil to anything and result in NSOrderedSame compareResult = [first1 compare:second1]; if (compareResult == NSOrderedSame) { NSString *first2 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumPersistentID]; NSString *second2 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumPersistentID]; compareResult = [first2 compare:second2]; if(compareResult == NSOrderedSame) { NSString *first3 = [(MPMediaItem*)a valueForProperty:MPMediaItemPropertyAlbumTrackNumber]; NSString *second3 = [(MPMediaItem*)b valueForProperty:MPMediaItemPropertyAlbumTrackNumber]; compareResult = [first3 compare:second3]; } } return compareResult; }]; } } 

您需要了解排序描述符 。

然后你的排序就像return [songs sortedArrayUsingDescriptors:sortDescriptors];一样简单return [songs sortedArrayUsingDescriptors:sortDescriptors]; 而且也应该快得多。

编辑:根据OP,MPMediaItem类不符合KVC,所以我正在退出答案。