I have an array of Habit objects which I am modifying in memory and a getter/setter to read and write it to documents storage as JSON whenever changes are made. I have split each object into its own JSON file and so far everything works, however changing one object in the array will re-write all the files. I understand this is what I instructed my setter to do, but is there a way to only write the objects in newValue that were changed?
extension Storage {
static var habits: [Habit] {
get { ... }
set {
newValue.forEach({
let data = try! JSONEncoder().encode($0)
do { try data.write(to: Storage.habitsFolder.appendingPathComponent("habit-\($0.id).json")) }
catch let error {
print("Failed to write Habit \($0.id): \(error.localizedDescription)")
}
})
}
}
}
The way I would make a change now is Storage.habits[0].name = "Some name". Which calls the setter, which then re-writes the files for each habit. So I was wondering if there's some way to detect which part of newValue changed or pass an index to it and only update that file.
Is the only way to go about this to have the array be get-only and use a different method for setting each habit file?
Thank you, and apologies if this is a silly question.
Update: adding Habit class for more context
class Habit: Codable, CustomStringConvertible {
// MARK: - Properties
var id: Int
var name: String?
var notes: String?
var icon: String
var repeatPattern: RepeatPattern
var entries: [HabitEntry]
var reminders: [Reminder]
init(id: Int, name: String?, notes: String?, icon: String, entries: [HabitEntry], reminders: [Reminder]) {
self.id = id
self.name = name
self.notes = notes
self.icon = icon
self.repeatPattern = RepeatPattern(pattern: 0, startDay: calendar.today, enabledWeekdays: [1,2,3,4,5,6,7], expectedTimes: 1)
self.entries = entries
self.reminders = reminders
}
var description: String { return "Habit id: \(id), named: \(name ?? "nil"), \nnotes: \(notes ?? "nil"), \nicon: \(icon), \nrepeatPattern: \(repeatPattern), \nentries: \(entries), \nreminders: \(String(describing: reminders))" }
}