问题
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