假设我有2个核心数据实体。学生实体和类实体。对于这个例子,一个学生只有一个班级,一个班级可以有很多学生。
我们也假设这些都是大班。也就是说,每个班级都有1000名学生。
Class实体如下:
NSString* name
NSArray* students
和学生实体:
NSString* name
Class* class
NSString* grade
在我的UI中,我想要显示一个类。我想展示具有一定年级的学生的数字。即对于一个1000名学生,50人有A,500人有B的200人有C ......等等。
从Core Data获取这些数据的最有效方法是什么?
我是最新的;使用NSFetchedResultsController并通过+ count查询传递一个组的获取请求。我正在使用NSFetchedResultsController,以便UI更新为具有某个等级更改的学生数量。但它很慢。
有没有办法在不查询的情况下获取此信息?即当学生被添加到课程中或他们的成绩发生变化时,课程中的属性会更新所有成绩计数。因此,当我想要计数时,它们只是类的属性,不需要查询。
有可能吗?
答案 0 :(得分: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
个元素(按描述的成本)。
答案 1 :(得分: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];
答案 2 :(得分:0)
在swift中非常简单。
let request = NSFetchRequest(entityName: "BWCoreDataNotification")
request.predicate = NSPredicate(format: "type = 'purchase_reward'")
var error: NSError?
let numberOfNotifications = NSManagedObjectContext.MR_defaultContext().countForFetchRequest(request, error: &error)