我有两个名为Expenses
和ExpensesCategory
的实体,Expenses
与CategoryExpenses
有关系,具有以下属性 -
name-expenseCategory,Destination - ExpensesCategory,inverse - expense。
ExpensesCategory
具有名为expenseCategory的字符串类型属性,Expenses
具有名为amount的属性。
现在我想获取由expenseCategory分组的费用和金额总和。
这是我的代码
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 <= %@) AND (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
任何帮助都将不胜感激。
答案 0 :(得分:5)
以下是您问题的答案。
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];
答案 1 :(得分:2)
在回答另一个问题时,我发现了这个问题中突出显示的特定错误的原因(&#34;传递给setPropertiesToFetch的属性/关系描述名称:必须与获取实体上的名称匹配&#34;)。我正在添加这个答案,以帮助那些寻求解决该错误的人。
此错误的原因是fetchRequest&#39; s propertiesToFetch
正在fetchRequest&#39; s entity
之前设置。更改代码的顺序应解决问题:
[fetchRequest setEntity:entity];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObjects:amtDescription, expressionDescription, nameDesc, nil]];
[fetchRequest setPropertiesToGroupBy:[NSArray arrayWithObject:nameDesc]];
[fetchRequest setResultType:NSDictionaryResultType];
Apple documentation很明显propertiesToFetch
中包含的属性和关系必须与属性名称匹配:
&#34;属性或关系描述的名称必须与获取请求的实体上的描述名称相匹配。&#34;
但是我花了很长时间才意识到,只要你设置propertiesToFetch
(而不是执行提取时),就会进行此测试,因此需要首先设置entity
答案 2 :(得分:1)
您将|expressionDescription|
NSExpressionDescription
传递给setPropertiesToFetch:
; setPropertiesToFetch:
只接受一个NSPropertyDescriptions
数组,因此会抛出异常。
NSExpressionDescriptions
允许NSPropertyDescriptions
和setPropertiesToGroupBy:
。
答案 3 :(得分:0)
你应该看一下pre-fetching技巧。在此网址中,您可以找到Employee
和Department
之间的示例。
希望有所帮助!