我在iOS编程工作了几周,还有很多需要学习的东西。我有一种包含MPMediaItems的NSMutableArray工作,但它有大约10秒的速度,有1200种物品,我正在寻找一种更快的方法。
我的最终目标是拥有一系列MPMediaItemCollection项目,每个项目代表一张专辑。我不能从MPMediaQuery(据我所知)得到这个,因为我需要从播放列表中获取歌曲。所以我正在对从特定播放列表(“过去4个月”)中获得的歌曲进行排序,然后构建我自己的集合数组。正如我所说,下面的方法有效但速度很慢。即使我只按MPMediaItemPropertyAlbumTitle排序,它仍然需要大约4秒钟(iPhone 4S)。
编辑:我应该提一下,我尝试了排序描述符,但我无法获得工作的关键。 E.g。NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"MPMediaItemPropertyAlbumTitle" ascending:YES];
返回错误
[<MPConcreteMediaItem 0x155e50> 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 = [playlist valueForProperty: MPMediaPlaylistPropertyName];
NSLog (@"%@", playlistName);
if ([playlistName isEqualToString:@"Last 4 months"]) {
/* replaced this code with a mutable copy
NSArray *songs = [playlist items];
for (MPMediaItem *song in songs) {
[songArray addObject:song];
}
*/
// the following replaces the above for-loop
songArray = [[playlist items] 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];
}];
}
}
答案 0 :(得分:3)
我知道这是一个旧线程,但我认为澄清为什么OPs排序代码不起作用很重要,以便任何遇到此代码的人都不会放弃使用NSSortDescriptors。
代码:
[[NSSortDescriptor alloc] initWithKey:@"MPMediaItemPropertyAlbumTitle" ascending:YES];
应该是:
[[NSSortDescriptor alloc] initWithKey:MPMediaItemPropertyAlbumTitle ascending:YES];
因为MPMediaItemPropertyAlbumTitle保存密钥的名称。
我多次使用过此代码。
答案 1 :(得分:2)
根据@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;
}];
}
}
答案 2 :(得分:0)
您需要了解sort descriptors。
然后你的排序就像return [songs sortedArrayUsingDescriptors:sortDescriptors];
一样简单,也应该快得多。
编辑:根据OP,MPMediaItem类不符合KVC标准,所以我正在退出答案。