如何通过valueForKey从fetch中对数组进行排序

时间:2014-06-15 00:23:48

标签: arrays sorting core-data nsdictionary nsfetchedresultscontroller

我有一个fetchResultController,它通过运行多个方法来编译数组。最后的单元格显示名称和编号(排名)。我想从tableview中取出单元格并按数字(升序)对它们进行排序。我在frc中尝试了nssortdescriptor,但是当我尝试调用'排名'时会遇到问题,因为它不是我正在获取的实体的关键路径。有没有一个地方我可以截取这个数组来自frc,按valueForKey排序:@“排名”?我该如何实现这种呢?

它循环创建valueForKey的方法如下:

- (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;
}

和带有单元格配置的frc在这里:

- (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"]];
}

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

正如我解释HERE,没有办法(AFAIK)根据ranking表达式进行排序。您必须在内存中对结果进行排序,从而完全取消对FRC的需求。

只需在给定的上下文上执行请求并在内存中排序:

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]];

results数组现在将保存您的已排序信息,将其用作表的数据源。 将results存储在视图控制器属性中,例如:

self.results = results;

此代码可能会以您的viewDidLoad方法为例。

在您访问FRC以获取对象的任何地方,您现在都可以访问您的表数据源以获取该信息(假设您只有1个部分):

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