NSSortDescriptor and NSPredicate for sorting and filtering

蓝咒 提交于 2019-12-08 09:39:37

问题


I have a tableView that has 5 different possible datasources depending on a flag object (NSNumber *)dataSourceAssignment. I've implemented an NSSortDescriptor that sorts dataSource by a (float)confidenceRating.

After the datasource is assigned, I need to be able to filter the dataSource array by a (NSString *)genre. I understand how to use NSPredicate to filter my array, but I can't figure out how to do it efficiently when there are 5-6 different genre strings that could be checked.

The user is able "check" multiple genres that should basically toggle the display of tracks according to which genres are selected. I was thinking of creating a dictionary in NSUserDefaults *defaults that would look something like this: ["genre1" = YES, "genre2" = NO, "genre3" = YES ...].

How can I set up NSPredicate to filter datasource using the genre dictionary without using a huge if/switch statement with loads of conditions.

Here is the code I have before a NSPredicate is implemented:

- (void)assignDataSource
{
switch (dataSourceAssignment.intValue) {
    case 0:     dataSource = [NSMutableArray arrayWithArray:tracksArray];           break;
    case 1:     dataSource = [NSMutableArray arrayWithArray:favoriteTracks];        break;
    case 2:     dataSource = [NSMutableArray arrayWithArray:topTracksOfTheWeek];    break;
    case 3:     dataSource = [NSMutableArray arrayWithArray:topTracksOfTheMonth];   break;
    case 4:     dataSource = [NSMutableArray arrayWithArray:topTracksOfTheYear];    break;
    default:    break;
}

if (dataSourceAssignment.intValue >= 2)  {
    NSSortDescriptor *avgRatingSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"confidenceRating" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:avgRatingSortDescriptor, nil];
    NSArray *sortedArray = [dataSource sortedArrayUsingDescriptors:sortDescriptors];
    dataSource = [NSMutableArray arrayWithArray:sortedArray];
}

回答1:


You can store which genres were selected into array and then use predicate. You can also remove/add elements when user select/deselect elements.

NSArray *selectedGenresByUser = [NSArray arrayWithObjects:@"genre1",@"genre2", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"genre in $SELECTED_GENRES"];
predicate = [predicate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:[NSArray arrayWithArray:selectedGenresByUser] forKey:@"SELECTED_GENRES"]];
//then use predicate to filter datasource array( maby you can store all elements in one array)



回答2:


When you use predicateWithFormat, you can pass it a regular expression statement about the predicate. That string is where you can do multiple predicates, and so that can be what you alter when different genres are selected.

For example, you can have: predicateWithFormat:predicateString, and then have predicateString set to be something along the lines of "SELF beginswith genre1 AND SELF beginswith genre1" if the user has selected genre1 and genre2. Though definitely doublecheck that regex I used, cause you need something better than that for it to work well.



来源:https://stackoverflow.com/questions/11786746/nssortdescriptor-and-nspredicate-for-sorting-and-filtering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!