Вы можете использовать ключевые пути для этого, поскольку ключевые пути не требуют inout
объявлений.
infix operator =!: AssignmentPrecedence
func =!<T, U: Equatable>(lhs: (T, ReferenceWritableKeyPath<T,U>), rhs: U) {
if lhs.0[keyPath: lhs.1] != rhs {
lhs.0[keyPath: lhs.1] = rhs
}
}
func >><T, U: Equatable>(lhs: T, rhs: ReferenceWritableKeyPath<T,U>) -> (T, ReferenceWritableKeyPath<T,U>) {
return (lhs, rhs)
}
Приведенный выше код создает оператор, который вы описали в вопросе, а также перегружает оператор >>
, чтобы создать пару Object + KeyPath и передать ее в =!
.
Использование будет где-то по следующим строкам:
class Person {
var age: Int = 0 {
didSet {
print("New age:", age)
}
}
}
let person = Person()
person>>\.age =! 4
person>>\.age =! 4
person>>\.age =! 4
person>>\.age =! 5
person>>\.age =! 5
По назначению код будет напечатан:
New age: 4
New age: 5
, даже если одно и то же значение было присвоено несколько раз подряд.