简体   繁体   English

使用多个对象集合中的第一项创建对象数组?

[英]Creating array of objects with first items from multiple object collections?

I am new to Objective C and iOS programming, and have wandered into waters that are a bit over my head. 我是Objective C和iOS编程的新手,涉足于我的脑海。 Any help is appreciated. 任何帮助表示赞赏。

I am having an issue sorting an array to use in a UITableView. 我在对要在UITableView中使用的数组进行排序时遇到问题。 Basically, I want to query a set of albums, and sort alphabetically or by date (ascending and descending) based on user settings. 基本上,我想查询一组专辑,并根据用户设置按字母顺序或按日期(升序和降序)排序。 First I synthesize some global arrays, and mediaquery the albums: 首先,我合成一些全局数组,然后媒体查询专辑:

@synthesize allSongs, arrayForTableView;
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
[songsQuery setGroupingType: MPMediaGroupingAlbum];
arrayForTableView = [songsQuery collections];
allSongs = [songsQuery items];

So far, so good. 到现在为止还挺好。 Albums sort alphabetically just like they should. 专辑按字母顺序排序。 The allSongs array is used for some playback functions elsewhere. allSongs数组用于其他位置的某些播放功能。 So now, I add in detection for the settings, as well as sort by the "year" property: 因此,现在,我添加了对设置的检测,并按“ year”属性进行了排序:

@synthesize allSongs, arrayForTableView;
MPMediaQuery *songsQuery = [MPMediaQuery songsQuery];
[songsQuery setGroupingType: MPMediaGroupingAlbum];
NSArray *allAlbums = [songsQuery collections];
allSongs = [songsQuery items];

if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"SortAlbumsMethod"] isEqualToString:@"0"]) {
    arrayForTableView = [songsQuery collections];
} else if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"SortAlbumsMethod"] isEqualToString:@"1"]) {
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"year"
                                                 ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    arrayForTableView = [allAlbums sortedArrayUsingDescriptors:sortDescriptors];
} else {
    NSSortDescriptor *sortDescriptor;
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"year"
                                                 ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    arrayForTableView = [allAlbums sortedArrayUsingDescriptors:sortDescriptors];
}

This is where I run into problems. 这是我遇到问题的地方。 The above doesn't work because each collection (album) does not have a year property. 上面的方法不起作用,因为每个集合(相册)都没有年份属性。 If I replace "allAlbums" with "allSongs," the code functions correctly. 如果我将“ allAlbums”替换为“ allSongs”,则代码可以正常运行。 Except that I now have an entry for every song. 除了我现在每首歌都有一个条目。 The label info displayed is only relevant to the album, and the navigation is based on AlbumPersistentID, so everything works great, I just have way too many duplicate entries (that appear identical, because the song name is not displayed). 显示的标签信息仅与专辑相关,并且导航基于AlbumPersistentID,因此一切正常,我的重复项太多了(由于没有显示歌曲名称,它们看起来是相同的)。

It seems like the obvious solution then is to create an array, lets call it "albumRepresentatives" with a single item from each collection in "allAlbums", and use that in the sort descriptor. 看来,显而易见的解决方案是创建一个数组,将其命名为“ albumRepresentativeatives”,并在“ allAlbums”的每个集合中添加一个项目,然后在排序描述符中使用它。 Each item would actually be a song and not an album, but the look and functionality would work nonetheless. 每个项目实际上都是一首歌,而不是专辑,但是外观和功能仍然可以使用。 Ideally, I'd like to compare all songs in each album, select one with the highest "year" property and add it to "albumRepresentatives". 理想情况下,我想比较每张专辑中的所有歌曲,选择“年份”属性最高的歌曲,然后将其添加到“ albumRepresentatives”。 Plan B would be to simply take the song at index 0 for each album collection. 计划B将是简单地将每个专辑集合的索引为0的歌曲。

Problem is that actually doing that is beyond my abilities at this point. 问题在于,实际上, 这样做超出了我的能力范围。 Any help would be greatly appreciated! 任何帮助将不胜感激!

One option could be to use set because they do not store duplicated objects and init it with content of your array. 一种选择是使用set,因为它们不存储重复的对象,而是使用数组的内容对其进行初始化。 You might need to override (possible add to category) isEqual to achieve it. 您可能需要重写(可能添加到类别)isEqual才能实现它。

Second option: 第二种选择:

//Could be added as category to MPMediaItem for example
+(MPMediaItem*)latestSongInAlbum:(NSArray*)songsInAlbum
    MPMediaItem *latestSong = nil;
    for (MPMediaItem *song in songsInAlbum) {
     if(!latestSong) {
      latestSong = song;
     } else if([[latestSong valueForProperty: MPMediaItemPropertyReleaseDate] compare:
      [song valueForProperty: MPMediaItemPropertyReleaseDate]] == NSOrderedAscending]) {
     latestSong = song;
     }
    }
 return latestSong;
}

than do something similar to this pseudocode: 比做与此伪代码类似的事情:

NSMutableArray* latestSongFromeachAlbum = [[NSMutableArray alloc] initWithCapacity:[allAlbums count]];
for( album in allAlbums) {
 NSIndexSet* indexes = [allSongs indexesOfObjectsPassingTest:(^)(id obj, NSUInteger idx, BOOL *stop)) {
      return album == obj.album;
 }];
 NSArray* songsInAlbum = [allSongs objectsAtIndexes:indexes];

 MPMediaItem* latestSong = [ExtendedClass latestSongInAlbum:songsInAlbum];

 //now you have pair latestSong(you can use it's date) in album and the album. You can store as you prefer
 [latestSongFromeachAlbum addObject:latestSong];
}

Hope it's complete enough. 希望它足够完整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM