15

使用Core Data,我遇到了一个问题。我有一个带有属性“数量”的实体“运动”。如何计算所有实例的所有“数量”的总和?我想了解如何使用NSExpressionDescription,但这已经足够了NSSet

4

3 回答 3

28

拥有 managedObjectContext:

NSManagedObjectContext *managedObjectContext = ...

我们创建一个返回类型字典的获取请求:

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Movement class])];
fetchRequest.resultType = NSDictionaryResultType;

然后我们创建一个表达式描述来计算总和:

NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
expressionDescription.name = @"sumOfAmounts";
expressionDescription.expression = [NSExpression expressionForKeyPath:@"@sum.amount"];
expressionDescription.expressionResultType = NSDecimalAttributeType;

将请求属性设置为获取:

fetchRequest.propertiesToFetch = @[expressionDescription];

如果需要,我们还可以设置谓词。

最后我们执行请求并获得一个数组,其中包含一个带有一个键的字典(@“sumOfAmounts”),它的值是一个带有金额总和的 NSNumber。

NSError *error = nil;
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (result == nil)
{
    NSLog(@"Error: %@", error);
}
else
{
    NSNumber *sumOfAmounts = [[result objectAtIndex:0] objectForKey:@"sumOfAmounts"];
}

干杯

于 2013-02-11T23:34:28.060 回答
20

这是一个使用and对托管对象的属性求和的Swift示例。该示例假定托管对象已命名并且要求和的属性是 。NSExpressionNSExpressionDescriptionMovementamount

例子:

 func sumAmount() -> Double {
    var amountTotal : Double = 0

    // Step 1:
    // - Create the summing expression on the amount attribute.
    // - Name the expression result as 'amountTotal'.
    // - Assign the expression result data type as a Double.

    let expression = NSExpressionDescription()
    expression.expression =  NSExpression(forFunction: "sum:", arguments:[NSExpression(forKeyPath: "amount")])
    expression.name = "amountTotal";
    expression.expressionResultType = NSAttributeType.doubleAttributeType

    // Step 2:
    // - Create the fetch request for the Movement entity.
    // - Indicate that the fetched properties are those that were
    //   described in `expression`.
    // - Indicate that the result type is a dictionary.

    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Movement")
    fetchRequest.propertiesToFetch = [expression]
    fetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType

    // Step 3:
    // - Execute the fetch request which returns an array.
    // - There will only be one result. Get the first array
    //   element and assign to 'resultMap'.
    // - The summed amount value is in the dictionary as
    //   'amountTotal'. This will be summed value.

    do {
        let results = try context.fetch(fetchRequest)
        let resultMap = results[0] as! [String:Double]
        amountTotal = resultMap["amountTotal"]!
    } catch let error as NSError {
        NSLog("Error when summing amounts: \(error.localizedDescription)")
    }

    return amountTotal
}

步骤的附加讨论:

第 1 步- 创建一个NSExpressionDescription变量。这NSExpressionDescription表明将哪种类型的函数应用于参数。sum函数正在应用于amount属性。

expression.expression =  NSExpression(forFunction: "sum:", 
    arguments:[NSExpression(forKeyPath: "amount")])

请注意,arguments参数是一个数组。您可以在数组中传递不同类型的表达式,但是,在我们的例子中,我们只需要amount属性。

第 2 步- 在此处建立获取请求。请注意,结果类型被指定为字典:fetchRequest.resultType = NSAttributeType.DictionaryResultType。在第 3 步中,我们将使用 的expression.nameamountTotal作为访问总和值的键。

第 3 步- 我们执行获取请求并返回一个元素数组。该元素将是一个字典,我们将其转换为[String:Double]: let resultMap = results[0] as! [String:Double]。字典的值是一个 Double,因为在第 1 步中我们指出这expression.expressionResultType将是一个 Double。

amountTotal最后,我们通过调用与键关联的字典值来访问总和:resultMap["amountTotal"]!


参考:

NSExpressionNSExpressionDescription

于 2016-02-10T19:13:55.813 回答
2

最好的方法是使用fetch 获取特定值并提供NSExpressionDescription 和sum:函数。

当你执行 fetch 时,你会得到一个单元素数组,其中包含一个字典,其键与表达式描述匹配,其值是表达式的结果。在这种情况下,您将获得一个sum键,其值将是给定表达式的属性之和。

于 2013-02-11T23:32:25.210 回答