Swift 在 setter 中检测数组中的哪个对象被更改
Swift detect in the setter which object in an array was changed
我有一个正在内存中修改的 Habit 对象数组和一个 getter/setter 以在进行更改时将其作为 JSON 读取和写入文档存储。我已将每个对象拆分到它自己的 JSON 文件中,到目前为止一切正常,但是更改数组中的一个对象将重新写入所有文件。我明白这是我指示 setter 做的,但是有没有办法只写入 newValue
中已更改的对象?
extension Storage {
static var habits: [Habit] {
get { ... }
set {
newValue.forEach({
let data = try! JSONEncoder().encode([=12=])
do { try data.write(to: Storage.habitsFolder.appendingPathComponent("habit-\([=12=].id).json")) }
catch let error {
print("Failed to write Habit \([=12=].id): \(error.localizedDescription)")
}
})
}
}
}
我现在要改变的方式是Storage.habits[0].name = "Some name"
。它调用 setter,然后为每个习惯重新写入文件。所以我想知道是否有某种方法可以检测 newValue 的哪一部分发生了变化或将索引传递给它并且只更新该文件。
解决这个问题的唯一方法是让数组只获取并使用不同的方法来设置每个习惯文件吗?
谢谢,如果这是一个愚蠢的问题,我们深表歉意。
更新:添加习惯 class 以获得更多上下文
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() {
.0 != .1
}.map{[=11=].0} /// from
for index in differentIndicies {
habitsToChange.append(newValue[index])
}
}
habitsToChange.forEach({ /// loop over the habits that have changed
do {
try JSONEncoder().encode([=11=]).write(to: habitsFolder.appendingPathComponent("habit-\([=11=].id).json"))
} catch {
print("Failed to write Habit \([=11=].id): \(error)")
}
})
existingHabits = newValue /// set existing to the new value
}
}
我有一个正在内存中修改的 Habit 对象数组和一个 getter/setter 以在进行更改时将其作为 JSON 读取和写入文档存储。我已将每个对象拆分到它自己的 JSON 文件中,到目前为止一切正常,但是更改数组中的一个对象将重新写入所有文件。我明白这是我指示 setter 做的,但是有没有办法只写入 newValue
中已更改的对象?
extension Storage {
static var habits: [Habit] {
get { ... }
set {
newValue.forEach({
let data = try! JSONEncoder().encode([=12=])
do { try data.write(to: Storage.habitsFolder.appendingPathComponent("habit-\([=12=].id).json")) }
catch let error {
print("Failed to write Habit \([=12=].id): \(error.localizedDescription)")
}
})
}
}
}
我现在要改变的方式是Storage.habits[0].name = "Some name"
。它调用 setter,然后为每个习惯重新写入文件。所以我想知道是否有某种方法可以检测 newValue 的哪一部分发生了变化或将索引传递给它并且只更新该文件。
解决这个问题的唯一方法是让数组只获取并使用不同的方法来设置每个习惯文件吗?
谢谢,如果这是一个愚蠢的问题,我们深表歉意。
更新:添加习惯 class 以获得更多上下文
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() {
.0 != .1
}.map{[=11=].0} /// from
for index in differentIndicies {
habitsToChange.append(newValue[index])
}
}
habitsToChange.forEach({ /// loop over the habits that have changed
do {
try JSONEncoder().encode([=11=]).write(to: habitsFolder.appendingPathComponent("habit-\([=11=].id).json"))
} catch {
print("Failed to write Habit \([=11=].id): \(error)")
}
})
existingHabits = newValue /// set existing to the new value
}
}