2013-02-11 60 views
5

使用核心数据时,我遇到了一个问题。我有一个具有“金额”属性的实体“运动”。我如何制作所有实例的“金额”的总和?我想了解如何使用NSExpressionDescription,但它足够好NSSet。核心数据所有实例的总和属性

回答

20

有一个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"]; 
} 

干杯

+1

为什么downvote? – e1985 2013-02-12 08:21:53

+0

对不起,这是我的不好,我想upvote ... Plz提供您的文章上的一个小编辑,所以我可以切换我的投票 – Yaman 2013-02-12 08:33:29

+0

谢谢你!效果很好! – Vins 2013-02-12 09:15:15

1

下面是使用NSExpressionNSExpressionDescription总结被管理对象的属性的斯威夫特例子。该示例假定被管理对象被命名为Movement并且总和属性为amount

实施例:

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(entityName: "Movement") 
    fetchRequest.propertiesToFetch = [expression] 
    fetchRequest.resultType = NSAttributeType.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.executeFetchRequest(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指示对参数应用什么类型的函数。 总和功能正在应用于数量属性。

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

注意,参数参数是一个阵列。您可以在数组中传递不同类型的表达式,但在我们的情况下,我们只需要amount属性。

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

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

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


参考文献:

NSExpressionNSExpressionDescription