核心数据获取记录按关系分组?

时间:2014-07-25 13:46:01

标签: ios objective-c core-data

screen shot added我有两个名为ExpensesExpensesCategory的实体,ExpensesCategoryExpenses有关系,具有以下属性 - 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

任何帮助都将不胜感激。

4 个答案:

答案 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允许NSPropertyDescriptionssetPropertiesToGroupBy:

答案 3 :(得分:0)

你应该看一下pre-fetching技巧。在此网址中,您可以找到EmployeeDepartment之间的示例。

希望有所帮助!