核心数据获取记录按关系分组?
我有两个名为Expenses
和ExpensesCategory
的实体, ExpensesCategory
与CategoryExpenses
有以下属性 – name-expenseCategory,Destination – ExpensesCategory,inverse-expense。 ExpensesCategory
有一个名为expenseCategory的字符串类型属性, Expenses
有一个名为amount的属性。 现在我想获取费用由amountCategory分组的费用。 这是我的代码
NSSortDescriptor *sortTitle =[NSSortDescriptor sortDescriptorWithKey:@"addedTimestamp" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObjects:sortTitle, nil]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Expense" inManagedObjectContext:context]; NSPredicate *predicate; predicate =[NSPredicate predicateWithFormat:@"(addedTimestamp = %@)",currentDate, endDate]; NSAttributeDescription* amtDescription = [entity.attributesByName objectForKey:@"amount"]; NSRelationshipDescription* nameDesc = [entity.relationshipsByName objectForKey:@"expenseCategory"]; NSExpression *keyPathExpression = [NSExpression expressionForKeyPath: @"amount"]; NSExpression *countExpression = [NSExpression expressionForFunction: @"sum:" arguments: [NSArray arrayWithObject:keyPathExpression]]; NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init]; [expressionDescription setName: @"Sum"]; [expressionDescription setExpression: countExpression]; [expressionDescription setExpressionResultType: NSDecimalAttributeType]; [fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:amtDescription, expressionDescription, nameDesc, nil]]; [fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObject:nameDesc]]; [fetchRequest setResultType:NSDictionaryResultType]; [fetchRequest setEntity:entity]; [fetchRequest setPredicate:predicate]; [fetchRequest setSortDescriptors:sortDescriptors]; [context executeFetchRequest:fetchRequest error:&error];
但是当我运行Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attribute/relationship description names passed to setPropertiesToFetch: must match name on fetch entity
得到Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attribute/relationship description names passed to setPropertiesToFetch: must match name on fetch entity
任何帮助,将不胜感激。
以下是您的问题的答案。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"ExpenseCategory" inManagedObjectContext:context]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:entity]; NSError *error; fetchRequest.predicate =[NSPredicate predicateWithFormat:@"(addedTimestamp <= %@) AND (addedTimestamp >= %@)",currentDate, endDate]; NSSortDescriptor *sortTitle =[NSSortDescriptor sortDescriptorWithKey:@"addedTimestamp" ascending:YES]; fetchRequest.sortDescriptors = [NSArray arrayWithObjects:sortTitle, nil]; NSExpressionDescription *ex = [[NSExpressionDescription alloc] init]; [ex setExpression:[NSExpression expressionWithFormat:@"@sum.expense.amount"]]; [ex setName:@"Sum"]; [ex setExpressionResultType:NSDecimalAttributeType]; [fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:@"expenseCategory", ex, nil]]; [fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObject:@"expenseCategory"]]; [fetchRequest setResultType:NSDictionaryResultType ]; // Execute the fetch. NSArray *matchingObjects = [context executeFetchRequest:fetchRequest error:&error]; if ([matchingObjects lastObject]) { for (id expenseCategory in matchingObjects) { NSLog(@"%@", expenseCategory); } }
如果您想要按Expense addedTime而不是ExpenseCategory addedTime进行过滤,则将谓词更改为:
fetchRequest.predicate =[NSPredicate predicateWithFormat:@"(expense.addedTimestamp <= %@) AND (expense.addedTimestamp >= %@)",currentDate, endDate];
在回答另一个问题的同时,我发现了这个问题中突出显示的特定错误的原因(“传递给setPropertiesToFetch的属性/关系描述名称:必须与获取实体上的名称匹配”)。 我正在添加这个答案,以帮助那些寻求解决该错误的人。
出现此错误的原因是fetchRequest的propertiesToFetch
正在fetchRequest的entity
之前设置。 更改代码的顺序应解决问题:
[fetchRequest setEntity:entity]; [fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:amtDescription, expressionDescription, nameDesc, nil]]; [fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObject:nameDesc]]; [fetchRequest setResultType:NSDictionaryResultType];
Apple文档很清楚, propertiesToFetch
包含的属性和关系必须与属性名称匹配:
“属性或关系描述的名称必须与获取请求的实体上的描述名称相匹配。”
但是我花了很长时间才意识到一旦你设置了propertiesToFetch
(而不是执行fetch)就进行了这个测试,因此需要先设置entity
。
你正在传递|expressionDescription|
,这是一个NSExpressionDescription
,to setPropertiesToFetch:
; setPropertiesToFetch:
接受只有NSPropertyDescriptions
的数组,因此抛出exception。
在setPropertiesToGroupBy:
允许使用NSExpressionDescriptions
和NSPropertyDescriptions
setPropertiesToGroupBy:
但是。
你应该看一下预取技术。 在这个url中,您可以找到Employee
和Department
之间的示例。
希望有所帮助!