How to sum a double attribute from CoreData in swift

后端 未结 2 664
-上瘾入骨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:26

    In your current code, you're attempting to cast logsArray as an array of doubles when it's in fact an array of NSManagedObjects. That's why you're getting an error when you attempt to reduce the array.

    To get the sum of the double values associated with your "totalWorkTimeInHours" key in Core Data, you have to access the "totalWorkTimeInHours" key from each NSManagedObject returned from your fetch request then add them together, ex:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        //CoreData
        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let managedContext : NSManagedObjectContext = appDelegate.managedObjectContext!
        var fetchRequest = NSFetchRequest(entityName: "Log")
        fetchRequest.returnsObjectsAsFaults = false;
        var results: NSArray = managedContext.executeFetchRequest(fetchRequest, error: nil)!
    
        var totalHoursWorkedSum: Double = 0
        for res in results {
            var totalWorkTimeInHours = res.valueForKey("totalWorkTimeInHours") as Double
            totalHoursWorkedSum += totalWorkTimeInHours
        }
    
        print("Sum = \(totalHoursWorkedSum)")
    }
    
    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题