Reputation: 615
Here is a Item entity In CoreData, and Item contains a property title(type is String?):
let item = Item(context: moc)
item.title = "hello world"
I want to calculate the sum of all Item.title.count:
let item_0 = Item(context: moc)
item_0.title = "a" // title.count is 1
let item_1 = Item(context: moc)
item_1.title = "ab" // title.count is 2
let item_2 = Item(context: moc)
item_2.title = "abc" // title.count is 3
// sum Item.title.count is 1 + 2 + 3 = 6
I don't want to looping through all Item objects,I would like to use something like the following:
let req = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
req.resultType = .dictionaryResultType
let countDesc = NSExpressionDescription()
countDesc.name = "titlesCount"
countDesc.expressionResultType = .integer64AttributeType
countDesc.expression = NSExpression(forFunction: "sum:", arguments: [NSExpression(forKeyPath: "title.count")])
req.propertiesToFetch = [countDesc]
let results = try moc.fetch(req) as! [NSDictionary] // Crash!!!
let dict = results.first!
let count = dict["titlesCount"] as! Int64
Unfortunately, the above code crashes as follows:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid keypath (continues after attribute name): title'
Is there a way to use NSExpression to sum Item.title.count? I don't want to iterate over all Items.
Thanks a lot! ;)
Upvotes: 1
Views: 64
Reputation: 541
how about obtaining the length of each Item and then summing them up?
let req = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
req.resultType = .dictionaryResultType
let countDesc = NSExpressionDescription()
countDesc.name = "titlesCount"
countDesc.expressionResultType = .integer64AttributeType
countDesc.expression = NSExpression(forFunction: "length:", arguments: [NSExpression(forKeyPath: "name")])
req.propertiesToFetch = [countDesc]
do {
let results = try moc.fetch(req) as! [NSDictionary]
return results.reduce(0) { $0 + ($1["titlesCount"] as! Int) } // this sums up all the individual item lengths
} catch {
print("Error fetching data from context \(error)")
}
I hope it helps! :)
Upvotes: 1