How to Sum the Numbers(Int16) of Stored Core Data - Swift 3

How to sum the numbers(Int16) of stored core data - Swift 3

You have already fetch the records, so get the sum of the Value attribute this way.

try! context.fetch(request) as! [NSManagedObject]
let sum = result.reduce(0) { $0 + ($1.value(forKey: "Value") as? Int16 ?? 0) }
print(sum)

How to sum filtered Core Data in SwiftUI?

I have found similar problem in this question:
Sum of (double) fetch request field
I have modified the code a little and came up with this solution:

import SwiftUI
import CoreData

struct DashboardView: View {
@Environment(\.managedObjectContext) var managedObjectContext
// FetchRequest with predicate set to "after now"
@FetchRequest(entity: NPTransaction.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.value, ascending: false)], predicate: NSPredicate(format: "date > %@", Date() as NSDate)) var fetchRequest: FetchedResults<NPTransaction>

// sum results using reduce
var sum: Int64 {
fetchRequest.reduce(0) { $0 + $1.value }
}

var body: some View {
NavigationView {
VStack(alignment: .leading) {

HStack {
VStack(alignment: .leading) {
Text("sum")
Text("\(sum)")
.font(.largeTitle)

}
Spacer()
}
.padding()

Spacer()
}.navigationBarTitle("Title")
}
}

}

struct DashboardView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return DashboardView().environment(\.managedObjectContext, context)
}
}

How to Sum in Core Data

no matter what it works as this:

let fetchRequest = NSFetchRequest<NSDictionary>(entityName:"Trade")

fetchRequest.predicate = NSPredicate(format: "year = %d and month = %d",year,month)

// sort by day
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "day", ascending: true)]

//group by day for sum
fetchRequest.propertiesToGroupBy = ["day"]
var expressionDescriptions = [AnyObject]()
var expD = NSExpressionDescription()

// select day
expD.name = "day"
expD.expression = NSExpression(forKeyPath: "day")
expD.expressionResultType = .integer16AttributeType

expressionDescriptions.append(expD)

//select @sum.amount as dailysum
expD = NSExpressionDescription()
expD.name = "total"
expD.expression = NSExpression(forFunction: "sum:", arguments: [NSExpression(forKeyPath: "amount")])
expD.expressionResultType = .integer16AttributeType

expressionDescriptions.append(expD)

fetchRequest.propertiesToFetch = expressionDescriptions
fetchRequest.resultType = .dictionaryResultType

var result = [Int:String]()

do {
let fetchResult = try viewContext.fetch(fetchRequest)
for item in fetchResult {
result[item.value(forKey: "day") as! Int] = String(describing: item.value(forKey: "total") as! Int)}
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}

return result

How do I use an SQL GROUP BY and SUM functions in a IOS CORE-DATA request in SWIFT?

Bear in mind that CoreData is not a relational database, so you should think of entities not "tables", and objects not "records". Note also that by convention, attribute names should not begin with Uppercase letters. That said, it is possible to construct a fetch to achieve what you want. The key steps are:

  1. create a fetch request
  2. specify an NSPredicate to filter according to your chosen criteria
  3. set the resultType to .DictionaryResultType (required for "Group By")
  4. set the properties to be included in the fetch (to get the sum(), this involves creating an NSExpression and associated NSExpressionDescription).
  5. set the properties to group by
  6. Create an NSSortDescriptor to order by name, descending
  7. Execute the fetch

See the following code:

let fetch = NSFetchRequest(entityName: "Transaction")
let predicate = NSPredicate(format: "Account_name like %@ AND Amount > %@", "Private*",NSNumber(double: 1000.0))
fetch.predicate = predicate
fetch.resultType = .DictionaryResultType
let sumExpression = NSExpression(format: "sum:(Amount)")
let sumED = NSExpressionDescription()
sumED.expression = sumExpression
sumED.name = "sumOfAmount"
sumED.expressionResultType = .DoubleAttributeType
fetch.propertiesToFetch = ["Account_name", sumED]
fetch.propertiesToGroupBy = ["Account_name"]
let sort = NSSortDescriptor(key: "Account_name", ascending: false)
fetch.sortDescriptors = [sort]
let results = managedObjectContext?.executeFetchRequest(fetch, error: nil) as NSArray?

The result will be an array of dictionaries, with keys "Account_name" and "sumOfAmount".

EDIT
To extract the value for a particular Account_name, use another predicate:

    let newPredicate = NSPredicate(format: "Account_name like %@", "toto")!
if let resultsArray = results { // to unwrap the optional
let filteredResults = resultsArray.filteredArrayUsingPredicate(newPredicate)
let sumOfAmount = (filteredResults[0] as NSDictionary)["sumOfAmount"] as Double
}

I've ignored the fact that the previous example filtered Account_name to those beginning "Private", and assumed you will have one (and only one) account with name "toto" (hence filteredResults[0]); your production code should check.

cant get the integer from core data atribute

executeFetchRequest() returns an array of managed objects.
You have to get a single element (e.g. the first), then retrieve the
value of the "currentLevel" attribute (which is a NSNumber)
and finally extract the Int16:

if let results = fetchedResults {
if count(results) > 0 {
let curLevel = results[0] // NSManagedObject
if let num = curLevel.valueForKey("currentLevel") as? NSNumber {
let cLevel = num.shortValue // Int16
println(cLevel)
} else {
println("level not set")
}
} else {
println("no objects found")
}
} else {
println("Could not fetch \(error), \(error!.userInfo)")
}

Instead of Key-Value coding with setValue/valueForKey() you can also
let Xcode create NSManagedObject subclasses. If you activate
the "use scalar properties for primitive data types" option then
you can access its

@NSManaged var currentValue: Int16

property directly.

swift : get the closest date stored in the core data

As you mentioned using Core Data, the right direction is to Fetch this objects (the contacts). Then you will have an Array of NSManagedObjects. If the fecth is successful you iterate them in a ´for in´ loop.
Inside this loop use ´.valueForKey´ to extract the dates and apply the rules you have created, returning the NsManagedObject or Atribute you want.

Swift: Storing states in CoreData with enums

You can extract raw Int16 value with .rawValue property of ObjStatus.

// compare
obj.state == ObjStatus.State1.rawValue

// store
obj.state = ObjStatus.State1.rawValue

But you might want to implement stateEnum accessor for it:

class StateFullManagedObject: NSManagedObject {
@NSManaged var state: Int16
var stateEnum:ObjStatus { // ↓ If self.state is invalid.
get { return ObjStatus(rawValue: self.state) ?? .State1 }
set { self.state = newValue.rawValue }
}
}

// compare
obj.stateEnum == .State1

// store
obj.stateEnum = .State1

// switch
switch obj.stateEnum {
case .State1:
//...
case .State2:
//...
case .State3:
//...
}

Core Data not saving the relationship

If each Folder can have many Dates, you need to set the dates relationship to be "to many".

When you set the Date object's folder property, CoreData sets the corresponding inverse relationship, ie. setting the Folder object's dates property. Because you have defined this as "to one", CoreData has to remove any existing Date for that folder. Hence the folder property for that existing Date is set to nil (which is what your fetch shows).

If you redefine the relationship as "to many", CoreData will use an NSSet for the dates property, so it can keep track of several different Dates for the same Folder.



Related Topics



Leave a reply



Submit