Sum values with one-to-many relationship [closed] - swift

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have two entities Transaction and Account. one Account holds many transactions. I use this piece of code to calculate the sum of all transactions (of all accounts):
let sum = transactions.map { $0.value }.reduce(0, +)
But I don't know how to sum transactions that belongs to each account. I have a ForEach that shows each account and I want to put also the sum of their transactions. Can someone point me to the right direction?
Edit:
Heres the core data model:
Account+CoreDataProperties.swift
#NSManaged public var bank: String?
#NSManaged public var name: String?
#NSManaged public var iban: String?
#NSManaged public var city: String?
#NSManaged public var postal: String?
#NSManaged public var street: String?
#NSManaged public var country: String?
#NSManaged public var transaction: NSSet?
public var wrappedName: String
name ?? "Unknown Account"
}
//...
Transaction+CoreDataProperties.swift
#NSManaged public var category: String?
#NSManaged public var comment: String?
#NSManaged public var date: Date?
#NSManaged public var name: String?
#NSManaged public var value: Double
#NSManaged public var account: Account?
public var wrappedName: String {
name ?? "Unknown Transaction"
}
public var wrappedComment: String {
comment ?? "Unknown Comment"
}
//...

It appears that each account records all of its transactions; iterate through the accounts and sum their transactions.
for account in accounts {
let sumForThisAccount = account.transactions.map { $0.value }.reduce(0, +)
}

Related

Repeating reference to CoreData Entity when debugging object in Swift

I may be simply understanding this incorrectly, but when I created an Exercise entity and looked at it contents in the debugger I get this repeating reference to the Entity type.
The Exercise+CoreDataProperties file is standard:
import Foundation
import CoreData
extension Exercise {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Exercise> {
return NSFetchRequest<Exercise>(entityName: "Exercise")
}
#NSManaged public var exerciseDuration: Int16
#NSManaged public var repeatNo: Int16
#NSManaged public var restDuration: Int16
#NSManaged public var exerciseName: String
#NSManaged public var id: UUID
#NSManaged public var associatedWorkout: NSSet?
}
// MARK: Generated accessors for associatedWorkout
extension Exercise {
#objc(addAssociatedWorkoutObject:)
#NSManaged public func addToAssociatedWorkout(_ value: WorkoutSet)
#objc(removeAssociatedWorkoutObject:)
#NSManaged public func removeFromAssociatedWorkout(_ value: WorkoutSet)
#objc(addAssociatedWorkout:)
#NSManaged public func addToAssociatedWorkout(_ values: NSSet)
#objc(removeAssociatedWorkout:)
#NSManaged public func removeFromAssociatedWorkout(_ values: NSSet)
}
extension Exercise : Identifiable {
}
And here is the xcdatamodeld config:
Any ideas why I cannot view the values of the object in debug mode once I've created it? Have I done something in my code to cause this repetition?
The variables view you're using can't see into the values of properties of managed objects (or of most objects). If you want to inspect the property values, use the debug console. When you're stopped on the line in your screenshot, you should be able to use po newExercise to see properties of newExercise, or you can use commands like po newExercise.exerciseName to see individual property values.

Designing data model for meal tracking app

Could help me with designing my data model, please?
I'm developing a meal tracking app that counts meal calories by calculation all included ingredients.
My current data model: Meal and Ingredient are CoreData entities.
Meal has a "to many" relationship to Ingredient, and Ingredient has "to one" Meal.
That works, but it's quite inconvenient. You have to retype all your ingredients for every meal even if you add them to other meals...
Meal keeps track of included Ingredients, and each Ingredient contains macros information and its size in Meal (basically, how many tomatoes you put in it).
My goal is to make "a catalog" of all user-added ingredients, so a user could search for them. But I'm struggling with the model design.
I thought to change the Ingredient relationship to "to many", but where do I save the quantity of every ingredient in the particular meal?
Also, I thought about making "a proxy" Ingredient that has connections to Meal and Ingredient but also keeps size:
Meal -> [List of proxies] -> Ingredient.
But I'm not sure if it's a good idea.
How would you do that?
CoreData Meal extension looks like this:
extension Meal {
...
#NSManaged public var name: String?
#NSManaged public var ingredients: NSSet?
}
And Ingredient:
extension Ingredient {
...
#NSManaged public var calories: Float
#NSManaged public var carbohydrates: Float
#NSManaged public var fats: Float
#NSManaged public var name: String?
#NSManaged public var psize: Float
#NSManaged public var protein: Float
#NSManaged public var meal: Meal?
}

Why can #NSManaged properties be stored in extensions?

How can the #NSManaged properties be in an extension when extensions can't contain stored properties? Why are they not the same as stored properties?
A popular format for core data files is a core data class, and then an extension containing the core data properties.
//User+CoreDataClass
#objc(User)
public class User: NSManagedObject {
var fullName: String {
return "\(firstName) \(lastName)"
}
}
//User+CoreDataProperties
extension User {
// Why can these #NSManaged properties live in an extension?
#NSManaged public var id: Int64
#NSManaged public var firstName: String
#NSManaged public var lastName: String
var storedProp: String // Error: Extensions must not contain stored properties
}
Technically #NSManaged properties are computed properties.
Core Data synthesizes getter and setter.

#NSManaged property cannot have an initial value

i'm trying to store my api data in core data entity. I have some custom data types array also in them. So i made those attributes transformable. Like this,
Now when i created the NSManagedObject class of my entity, it's showing me error,
#NSManaged property cannot have an initial value.
My SingleChat+CoreDataProperties.swift class is this,
extension SingleChat {
#nonobjc public class func fetchRequest() -> NSFetchRequest<SingleChat> {
return NSFetchRequest<SingleChat>(entityName: "SingleChat")
}
#NSManaged public var name: String?
#NSManaged public var roomSID: String?
#NSManaged public var isGroup: Bool
#NSManaged public var lastMessage: String?
#NSManaged public var lastMsgTime: String?
#NSManaged public var lastMsgTimeActual: String?
#NSManaged public var profilePic: String?
#NSManaged public var lastMsgRead: Bool
#NSManaged public var unReadMsgsCount: Int16
#NSManaged public var actualNameFor_1_2_1_chat: String?
#NSManaged public var isNewGroup: Bool
#NSManaged public var members = [TCHMember]()
#NSManaged public var messages = [TCHMessage]()
#NSManaged public var twChannelObj: TCHChannel?
#NSManaged public var group_info: [String:JSON]?
}
I'm new to core data and does not know how i can get custom data types. How i can get resolve this issue, I want to store data in members, messages and group_info. These are arrays.

Core Data One to Many Relationship not saving correctly/as expected

I have a core data project that includes the following NSManagedObjects:
********************** FSDJump NSManaged Object
extension FSDJump {
#nonobjc public class func fetchRequest() -> NSFetchRequest<FSDJump> {
return NSFetchRequest<FSDJump>(entityName: "FSDJump")
}
#NSManaged public var starSystem: String
#NSManaged public var starPos: NSArray
#NSManaged public var bodyName: String
#NSManaged public var jumpDist: Float
#NSManaged public var fuelUsed: Float
#NSManaged public var fuelLevel: Float
#NSManaged public var boostUsed: Bool
#NSManaged public var systemFaction: String
#NSManaged public var systemAllegiance: String
#NSManaged public var systemEconomy: String
#NSManaged public var systemGoverment: String
#NSManaged public var systemSecurity: String
#NSManaged public var powers: NSArray
#NSManaged public var powerplayState: String
#NSManaged public var timeStamp: String
#NSManaged public var factionState: String
#NSManaged public var factions: NSSet
}
// MARK: Generated accessors for factions
extension FSDJump {
#objc(addFactionsObject:)
#NSManaged public func addToFactions(_ value: Factions)
#objc(removeFactionsObject:)
#NSManaged public func removeFromFactions(_ value: Factions)
#objc(addFactions:)
#NSManaged public func addToFactions(_ values: NSSet)
#objc(removeFactions:)
#NSManaged public func removeFromFactions(_ values: NSSet)
}
********************** Factions NSManaged Object
extension Factions {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Factions> {
return NSFetchRequest<Factions>(entityName: "Factions")
}
#NSManaged public var name: String
#NSManaged public var allegiance: String
#NSManaged public var factionState: String
#NSManaged public var government: String
#NSManaged public var influence: Float
#NSManaged public var fsdJump: FSDJump
}
with a one to many relationship defined between FSDJump and Factions (i.e. one FSDJump may have multiple factions (with the inverse relationship defined as 'fsdJump').
I use the following code to save multiple Factions (where they exist) within an 'if else' statement saves each fsdJumpEvent.
if fsdJumpEvent["Factions"].exists() {
// save all of the Faction array objects in the variable arrayOfFactions
let arrayOfFactions = fsdJumpEvent["Factions"]
// create a newFaction managedObject to save the faction details to
let newFaction = (Factions(context: contextTCCEDJ))
for faction in arrayOfFactions {
// the following is strictly not necesary but it makes the code easier to read
// first allocate the values from faction to a local variable then allocate that variable to the newFaction managedObject
// Note faction is a tuple (string, JSON) so the construct 'faction.1' accesses the second value in the tuple
// 'faction.0' would access the first value in the tuple which is the array index "0", "1", "2", etc
let newFactionName = faction.1["Name"].string!
let newFactionState = faction.1["FactionState"].string!
let newFactionGovernment = faction.1["Government"].string!
let newFactionAllegiance = faction.1["Allegiance"].string!
let newFactionInfluence = faction.1["Influence"].float!
newFaction.name = newFactionName
newFaction.allegiance = newFactionAllegiance
newFaction.government = newFactionGovernment
newFaction.influence = newFactionInfluence
newFaction.factionState = newFactionState
// Add the new object to the context allowing it to be saved.
fsdJump.addToFactions(newFaction)
print("Faction added \(newFaction)")
}
}
The code appears to work. It builds, it runs and the print("Faction added \(newFaction)") statement prints multiple Factions per FSDJump as expected when they exist and as per the source data file I am using (JSON).
I can fetch the results and display them in a NSTableView. I can load data without any problems for the FSDJump managed object and display that in a NSTableView.
The fetch code is:
// Function returns all of the Factions associated with the timeStamp related entry in FSDJumps using the fsdJump relationship
func eventFactionsFetchSavedDataFromPersistenStore (contextTCCEDJ: NSManagedObjectContext, timeStamp: String) -> [Factions] {
var result = Array<Factions>()
let localFetchRequest = Factions.fetchRequest() as NSFetchRequest
localFetchRequest.predicate = NSPredicate(format:"fsdJump.timeStamp == '\(timeStamp)'")
do {
result = try contextTCCEDJ.fetch(localFetchRequest)
} catch {
print("Error in returning Factions event saved data from the persistent store")
}
print(result.count)
for reSult in result {
print(reSult.fsdJump.timeStamp)
}
return result
}
However, it only seems to save the last 'faction' for each relationship - rather than the multiple factions that are shown in the for faction in arrayOfFactions loop. Because the fetch statement only returns one Faction per fetch. Even if I remove the predicate statement it returns all of the saved factions but again only one has been saved per fsdJumpEvent instead of the multiple factions that are identified by the print statement.
I have tried everything I can think of. I have not been able to find a previous question that relates to this specific issue.
Am I using the 'addToFactions' function incorrectly?
Any help would be gratefully received.
(And yes - for any Elite Dangerous fans out there I am writing a macOS app to parse my journal files as a companion app to my windows version of Elite Dangerous.)
You are creating a new, single instance of newFaction outside of your for faction in arrayOfFactions loop. So that single newFaction is used each time the loop runs and just assigns new values to it (overwriting previous values) resulting in it ending up with the last set of values. Hence you seeing a single faction with the 'last' set of values. Move the line:
Let newFaction = Factions(context: contectTCCEDJ)
Inside (at the beginning) of the for in loop.
Edit: you are adding your faction to a Set (which by definition requires unique entities) so all you're currently doing is re-adding the same faction each time rather than a new one. To-many relationships point to a Set.