How to sum a double attribute from CoreData in swift

后端 未结 2 695
-上瘾入骨i
-上瘾入骨i 2021-01-07 13:57

I asked a similar question here: Getting the sum of an array of doubles in swift

but I still haven\'t gotten to a solution. Since the last question I changed my core

2条回答
  •  我在风中等你
    2021-01-07 14:27

    You can use reduce to add the double values of the fetched managed objects. In the "combining closure" you have to get the double value of the totalWorkTimeInHours attribute:

    let fetchRequest = NSFetchRequest(entityName: "Log")
    
    var error : NSError?
    let results = managedContext.executeFetchRequest(fetchRequest, error: &error)
    if let logs = results as? [Log] {
        let totalHoursWorkedSum = reduce(logs, 0.0) { $0 + $1.totalWorkTimeInHours.doubleValue }
        println(totalHoursWorkedSum)
    } else {
        println("fetch failed: \(error?.localizedDescription)")
    }
    

    Alternatively you can use "Key-Value Coding" to sum the double values in the array of fetched objects. This is quite similar to Lyndseys's answer, only without an explicit loop:

    let fetchRequest = NSFetchRequest(entityName: "Log")
    var error : NSError?
    
    if let results  = managedContext.executeFetchRequest(fetchRequest, error: &error) {
        let logs = results as NSArray
        let sum = logs.valueForKeyPath("@sum.totalWorkTimeInHours") as NSNumber
        let totalHoursWorkedSum = sum.doubleValue
        println(totalHoursWorkedSum)
    } else {
        println("fetch failed: \(error?.localizedDescription)")
    }
    

    But there is a better way: You create an "expression description" for the sum of all totalWorkTimeInHours values:

    let expressionDesc = NSExpressionDescription()
    expressionDesc.name = "sumOftotalWorkTimeInHours"
    expressionDesc.expression = NSExpression(forFunction: "sum:",
             arguments:[NSExpression(forKeyPath: "totalWorkTimeInHours")])
    expressionDesc.expressionResultType = .DoubleAttributeType
    

    and then a fetch request which fetches only this sum:

    let fetchRequest = NSFetchRequest(entityName: "Log")
    fetchRequest.propertiesToFetch = [expressionDesc]
    fetchRequest.resultType = .DictionaryResultType
    
    var error : NSError?
    if let results  = managedContext.executeFetchRequest(fetchRequest, error: &error) {
        let dict = results[0] as [String:Double]
        let totalHoursWorkedSum = dict["sumOftotalWorkTimeInHours"]!
        println(totalHoursWorkedSum)
    } else {
        println("fetch failed: \(error?.localizedDescription)")
    }
    

    The advantage is that the sum is calculated on the SQLite level, you don't have to fetch all the objects into memory.

    A possible disadvantage is that this request only fetches the values that are stored in the persistent store, and ignores any unsaved changes in the mangaged object context.

提交回复
热议问题