Alternatively with the AccessTracker idea:
@dynamicMemberLookup
struct AccessTracker<Value> {
private var value: Value
init(_ value: Value) {
self.value = value
}
subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T {
value[keyPath: keyPath]
}
subscript<T: Equatable>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
get {
value[keyPath: keyPath]
}
set {
if value[keyPath: keyPath] != newValue {
value[keyPath: keyPath] = newValue
}
}
}
}
The usage could be:
var reminder = AccessTracker(Reminder())
let old = reminder.fireDate
reminder.fireDate = old // no change
reminder.fireDate = old + 1 // change
var reminderRef = AccessTracker(ReminderRef())
reminderRef.fireDate = old // no change
reminderRef.fireDate = old + 1 // change