3

假设我有 2 个核心数据实体。一个学生实体和一个班级实体。对于这个例子,一个学生正好在一个班级,一个班级可以有很多学生。

我们还假设这些是大类。也就是说,每个班级有 1000 名学生。

Class 实体如下所示:

NSString* name
NSArray* students

和学生实体:

NSString* name
Class* class
NSString* grade

在我的 UI 中,我想显示一个类。我想显示具有特定成绩的学生数量。即对于一个有 1000 名学生的班级,50 人获得 A,500 人获得 B,200 人获得 C……以此类推。

从 Core Data 获取这些计数的最有效方法是什么?

我是最新的;y 使用 NSFetchedResultsController 并将其传递给 group by + count 查询的获取请求。我正在使用 NSFetchedResultsController 以便 UI 会随着具有特定成绩的学生数量的变化而更新。虽然它很慢。

有没有办法在不查询的情况下获取这些信息?即,当学生被添加到班级或他们的成绩发生变化时,班级上的一个属性会更新所有的成绩计数。所以当我想要计数时,它们只是类的一个属性,不需要查询。

是否可以?

4

3 回答 3

9

你可以试试这个获取请求:

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Student"];
[request setResultType:NSDictionaryResultType];
NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@"grade"];
NSExpression *countExpression = [NSExpression expressionForFunction:@"count:" arguments:[NSArray arrayWithObject:keyPathExpression]];

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"gradeTypeCount"];
[expressionDescription setExpression:countExpression];
[expressionDescription setExpressionResultType:NSInteger64AttributeType];
[request setPropertiesToFetch:@[@"grade",expressionDescription]];
[request setPropertiesToGroupBy:@[@"grade"]];
[request setPredicate:[NSPredicate predicateWithFormat:@"theClass == %@",cls.objectID]];

这将导致包含所需值的字典数组。
这里的问题是您的 FRC 将无法跟踪这些结果的更改。因此没有理由首先使用 FRC
即便如此,这是一个非常轻量级的请求,您可以在给定的时间间隔发出它并更新您的 UI。

(比如 2 秒,由于您不再处理托管对象,因此您可以在后台完成整个过程并将结果转储到主线程)

或者听一下你的主要上下文的变化,如果一个学生元素发生了变化,你再次重新获取计数。

这将避免Student一起获取任何元素(以所述成本)。

于 2013-04-08T08:36:50.663 回答
5

您可以使用以下示例在给定条件下获取计数。您不需要获取数据进行计数。您可以使用countForFetchRequest方法来有效地计算对象。

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[NSEntityDescription entityForName:entityName inManagedObjectContext:moc]];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
        @"grade=='A'"];
    [request setPredicate:predicate];

    NSError *err;
    NSUInteger count = [moc countForFetchRequest:request error:&err];
    if(count == NSNotFound) {
      //Handle error
    }

    [request release];
于 2013-04-08T04:55:53.077 回答
0

快速的非常简单的方法。

let request = NSFetchRequest(entityName: "BWCoreDataNotification")
request.predicate = NSPredicate(format: "type = 'purchase_reward'")

var error: NSError?
let numberOfNotifications = NSManagedObjectContext.MR_defaultContext().countForFetchRequest(request, error: &error)
于 2016-05-02T08:54:04.483 回答