我有一个具有十进制Transaction
属性的CoreData实体amount
。我想获取由谓词过滤的所有金额的总和。
Altohugh有解决方案using loops,我想直接在CoreData because of performance中进行(并了解NSExpression
)。
以下代码按预期工作,但是,正如我所说,这不是我想要的
// Easy way: Fetch all and use `value(forKeyPath:)`
let transactionFetch = NSFetchRequest<NSManagedObject>(entityName: CoreDateWrapper.Entity.Transaction)
var results: [NSManagedObject] = []
do {
results = try wrapper.context.fetch(transactionFetch)
} catch {
print("Error: \(error.localizedDescription)")
}
print((results as NSArray).value(forKeyPath: "@sum.\(CoreDateWrapper.Attribute.amount)") as! Decimal)
现在,我想使用NSExpression
,但是获取结果始终是一个空数组。
// Setup the expression and expression-description
let amountExpression = NSExpression(forKeyPath: CoreDateWrapper.Attribute.amount)
let sumExpression = NSExpression(forFunction: "sum:", arguments: [amountExpression])
let sumDescription = NSExpressionDescription()
sumDescription.expression = sumExpression
sumDescription.expressionResultType = .decimalAttributeType
sumDescription.name = "sum"
// Setup the fetchRequest to only get the sum.
// I expect a dictionary as a result instead of a `NSManagedObject`
let sumFetch = NSFetchRequest<NSDictionary>(entityName: CoreDateWrapper.Entity.Transaction)
sumFetch.propertiesToFetch = [sumDescription]
sumFetch.resultType = .dictionaryResultType
// Fetch the sum
var sumResult: [String: Decimal]? = nil
do {
let array = try wrapper.context.fetch(sumFetch)
if let res = array.first as? [String: Decimal] {
sumResult = res
} else {
print("Wrong type for result")
}
} catch {
print("Error fetching result: \(error.localizedDescription)")
}
// Output the sum
if let sum = sumResult?["sum"] {
print("Total: \(sum)")
}
这总是打印错误的类型 ,因为array
为空。