1

我必须提出一个复杂的核心数据获取请求,但我不知道是否可以提出。这是我的场景:只有一个具有以下属性的实体(费用):

  • 成本(NSDecimalNumber)
  • 存款(NSDecimalNumber)
  • 类别(NSString)
  • 付费(布尔值)

该请求应返回 3 个最昂贵的类别,但这些是必须遵守的规则:

  • 如果Paid == YES,应将费用成本添加到费用类别总计中
  • 如果Paid == NO && Deposit > 0,则应将费用押金添加到费用类别总额中
  • 如果Paid == NO,则不应将任何内容添加到 Expense 类别总计

使用 NSExpression,我可以计算每个类别的每个总数,但它还包括未支付的费用成本。有没有办法做到这一点?太感谢了!

4

1 回答 1

1

例如,您可以使用NSFetchRequest

// Build the fetch request
NSString *entityName = NSStringFromClass([Expense class]);
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;

仅过滤相关费用:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(paid == YES) OR ((paid == NO) AND (deposit > 0))"];
request.predicate = predicate;

并总结 cost 和 depost 属性:

NSExpressionDescription *(^makeExpressionDescription)(NSString *, NSString *) = ^(NSString *keyPath, NSString *name)
{
    // Create an expression for the key path.
    NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:keyPath];

    // Create an expression to represent the function you want to apply
    NSExpression *totalExpression = [NSExpression expressionForFunction: @"sum:" arguments: @[keyPathExpression]];

    NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];

    // The name is the key that will be used in the dictionary for the return value
    expressionDescription.name = name;
    expressionDescription.expression = totalExpression;
    expressionDescription.expressionResultType = NSDecimalAttributeType;

    return expressionDescription;
};

NSExpressionDescription *totalCostDescription = makeExpressionDescription(@"cost", @"totalCost");
NSExpressionDescription *totalDepositDescription = makeExpressionDescription(@"deposit", @"totalDeposit");

// Specify that the request should return dictionaries.
request.resultType = NSDictionaryResultType;

request.propertiesToFetch = @[categoryDescription,
                              paidDescription,
                              totalCostDescription,
                              totalDepositDescription];

并按类别和付费状态对结果进行分组:

// Get 'category' and 'paid' attribute descriptions
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName
                                              inManagedObjectContext:context];
NSDictionary *attributes = [entity attributesByName];
NSAttributeDescription *categoryDescription = attributes[@"category"];
NSAttributeDescription *paidDescription = attributes[@"paid"];

// Group by 'category' and 'paid' attributes
request.propertiesToGroupBy = @[categoryDescription, paidDescription];

您将获得汇总的已付和未付费用

NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];

您需要做的就是组合(和排序)然后:

if (results) {
    NSMutableDictionary *combined = [NSMutableDictionary dictionary];

    for (NSDictionary *result in results) {
        NSString *category = result[@"category"];

        BOOL paid = [result[@"paid"] boolValue];

        NSDecimalNumber *total = result[paid ? @"totalCost" : @"totalDeposit"];

        NSDecimalNumber *sum = combined[category];

        if (sum) {
            total = [total decimalNumberByAdding:sum];
        }

        combined[category] = total;
    }

    NSArray *sortedCategories = [combined keysSortedByValueUsingSelector:@selector(compare:)];

    [sortedCategories enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"Category %@: %@", obj, combined[obj]);
    }];
}
else {
    NSLog(@"Error: %@", error);
}
于 2013-08-31T21:51:16.037 回答