Ответ 1
Если все, что мы хотим, это сделать некоторые дополнительные функции после того, как selected
свойство было установлено, мы можем просто переопределить, чтобы добавить наблюдателя свойства:
override var selected: Bool {
didSet {
if self.selected {
// do something
}
}
}
Обновленный ответ для Swift 5:
override var isSelected: Bool {
didSet {
if self.isSelected {
// do something
}
}
}
Если мы заботимся о том, что предыдущее значение selected
было, мы можем получить доступ к нему через oldValue
:
didSet {
if self.selected == oldValue {
return
}
// do something
}
Обновленный ответ для Swift 5:
didSet {
if self.isSelected == oldValue {
return
}
// do something
}
И не забывайте, что мы можем использовать willSet
если нам нужно что-то сделать непосредственно перед изменением значения.
Мне было любопытно, что произойдет, когда у нас будет большая иерархия классов, каждый из которых будет добавлять свои собственные вещи в наблюдатели свойств willSet
и didSet
, поэтому я создал следующий тест:
class ClassA {
var _foo: Int = 0
var foo: Int {
set(newValue) {
println("Class A setting foo")
self._foo = newValue
}
get {
return self._foo
}
}
}
class ClassB: ClassA {
override var foo: Int {
willSet {
println("Class B will set foo")
}
didSet {
println("Class B did set foo")
}
}
}
class ClassC: ClassB {
override var foo: Int {
willSet {
println("Class C will set foo")
}
didSet {
println("Class C did set foo")
}
}
}
Теперь, если мы создадим объект ClassC
и установим его свойство foo
:
var c: ClassC = ClassC()
c.foo = 42
Мы получаем следующий вывод:
Class C will set foo
Class B will set foo
Class A setting foo
Class B did set foo
Class C did set foo
Итак, важно отметить несколько вещей из этого...
- Дочерний класс
willSet
вызывается перед его родительскимwillSet
. - Дочерний класс
didSet
вызывается после родительскогоdidSet
. - Создание переопределения ради добавления наблюдателей свойств не заменяет никаких наблюдателей свойств в родительских классах.
Первые два пункта имеют смысл. И на самом деле, это делает наблюдателей за недвижимостью гораздо привлекательнее. По сути, Свифт заставляет нашу руку подниматься и опускаться по иерархии соответствующим образом и красиво разделяет ее на два отдельных метода. Swift также не позволяет нам (я полагаю) переопределить свойство родительского класса, но также позволяет наблюдать изменения этого свойства - это намного лучше, чем подход Objective-C.
Но третий пункт, пожалуй, самый важный. Будьте осторожны - вы можете легко увязнуть в огромной иерархии кода didSet
и willSet
который замедляет процесс, который должен быть довольно быстрым: установка значения свойства.