问题描述
我有一个要在内存中修改的Habit对象数组,以及一个进行更改的getter / setter,以将其作为JSON读写到文档存储中。我已经将每个对象拆分为自己的JSON文件,到目前为止一切正常,但是更改数组中的一个对象将重新写入所有文件。我了解这是我指示设置员执行的操作,但是有没有办法只在newValue
中写入已更改的对象?
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)")
}
})
}
}
}
我现在要进行更改的方式是Storage.habits[0].name = "Some name"
。它调用设置程序,然后为每个习惯重写文件。因此,我想知道是否有某种方法可以检测到newValue的哪一部分已更改或向其传递索引而仅更新该文件。
要做到这一点,唯一的方法是使数组成为仅获取对象并使用不同的方法来设置每个习惯文件吗?
谢谢您,如果这是一个愚蠢的问题,我们深表歉意。
更新:添加Habit类以获得更多上下文
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))" }
}
解决方法
您可以创建一个属性来首先存储现有的habits
class Storage {
static var existingHabits = [Habit]()
}
然后,在set
内部,查看哪些Habit
是新的:
static var habits: [Habit] {
get { ... }
set {
var habitsToChange = [Habit]()
if existingHabits.count == 0 { /// it's empty,just write with newValue
habitsToChange = newValue
} else {
let differentIndicies = zip(existingHabits,newValue).enumerated().filter() {
$1.0 != $1.1
}.map{$0.0} /// from https://stackoverflow.com/a/30685226/14351818
for index in differentIndicies {
habitsToChange.append(newValue[index])
}
}
habitsToChange.forEach({ /// loop over the habits that have changed
do {
try JSONEncoder().encode($0).write(to: habitsFolder.appendingPathComponent("habit-\($0.id).json"))
} catch {
print("Failed to write Habit \($0.id): \(error)")
}
})
existingHabits = newValue /// set existing to the new value
}
}