how to sort array from fetch by valueForKey

谁说胖子不能爱 提交于 2019-12-12 02:46:22

问题


I have a fetchResultController that compiles an array by running through multiple methods. The final cells display a name and number (ranking). I'd like to take the cells from the tableview and sort them by the number (ascending). I've tried nssortdescriptor in the frc but run into issues when I try to call the 'ranking' because it isn't a keypath of the entity I'm fetching. Is there a place I can intercept this array that comes out of the frc to sort by valueForKey:@"ranking"? How would I implement this sort?

The methods it cycles through to create the valueForKey is here:

- (NSExpressionDescription*) rankingExpressionDescriptionForTags:(NSSet*)itemToTag
{
    NSPredicate* p2 = [NSPredicate predicateWithFormat:@"SUBQUERY(itemToTag,$t,$t.tagName IN %@).@count > 0",[itemToTag valueForKey:@"tagName"]];
    NSExpression* rankExpresion = [(NSComparisonPredicate*)p2 leftExpression];
    NSExpressionDescription* rankExpDesc = [[NSExpressionDescription alloc] init];
    rankExpDesc.name = @"ranking";
    rankExpDesc.expression = rankExpresion;
    rankExpDesc.expressionResultType = NSInteger64AttributeType;

    return rankExpDesc;
}

- (NSExpressionDescription*) objectIDExpressionDescription
{
    NSExpressionDescription* expDesc = [[NSExpressionDescription alloc] init];
    expDesc.name = @"objectID";
    expDesc.expressionResultType = NSObjectIDAttributeType;
    expDesc.expression = [NSExpression expressionForEvaluatedObject];
    return expDesc;
}

- (NSFetchRequest*) rankingRequestForItem:(Item*)item 
{
    NSFetchRequest* r = [NSFetchRequest fetchRequestWithEntityName:@"Item"];
    NSPredicate* p = [NSPredicate predicateWithFormat:@"SELF != %@",item.objectID];
    r.resultType = NSDictionaryResultType;


    r.propertiesToFetch = @[[self objectIDExpressionDescription],@"itemName",
                            [self rankingExpressionDescriptionForTags:[item mutableSetValueForKey:@"itemToTag"]]];


    r.predicate = p;
    r.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"itemName" ascending:YES]];


    return r;
}

and the frc with cell config is here:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSLog(@"selected item: %@, itemToTag: %@",selectedItem.itemName,[selectedItem.itemToTag valueForKey:@"tagName"]);
    NSFetchRequest *fetchRequest = [self rankingRequestForItem:selectedItem];
    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".


    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}


- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ - %@",[item valueForKey:@"itemName"],[item valueForKey:@"ranking"]];
}

Thanks for the help!


回答1:


As I explained HERE, there is no way (AFAIK) to sort based on the ranking expression. You will have to sort the results in-memory, thus nullifying completely the need for a FRC.

Simply execute the request on the given context and sort in-memory:

NSError* error = nil;
NSFetchRequest* r = [self rankingRequestForItem:selectedItem];
NSArray* results = [context executeFetchRequest:r error:&error];
NSSortDescriptor* sd = [NSSortDescriptor sortDescriptorWithKey:@"ranking" ascending:NO];
results = [results sortedArrayUsingDescriptors:@[sd]];

The results array will now hold your sorted information, use it as a datasource for your table. Store the results in a view controller property like:

self.results = results;

This code might go in your viewDidLoad method for example.

everywhere you access the FRC to get an object, you now access your table datasource for that information (assuming you have only 1 section):

NSIndexPath* someIndexPath = //some index path you might get as parameter
[self.results objectAtIndex:someIndexPath.row]; //return NSDictionary


来源:https://stackoverflow.com/questions/24225496/how-to-sort-array-from-fetch-by-valueforkey

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