Видеокурсы по изучению языка программирования Swift. Подробнее

Наблюдатели свойства

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

Наблюдатели свойства наблюдают и реагируют на изменения значения свойства. Наблюдатели свойства вызываются каждый раз, как присваивается новое значение свойству, даже если новое значение такое же как и старое.

Вы можете добавить наблюдатели свойства для любого хранимого свойства, которое вы объявили, кроме свойств ленивого хранения. Вы так же можете добавить наблюдателя для наследованного свойства (не важно вычисляемое оно или просто хранимое) путем переопределения свойства внутри подкласса. Вам не нужно определять наблюдателей свойств для непереопределяемых вычисляемых свойств, потому что вы можете наблюдать и реагировать на изменения в их значении в сеттере вычисленного свойства. Переопределение свойств описано в разделе Переопределение.

У вас есть опция определять один или оба этих наблюдателя свойства:

  • willSet вызывается прямо перед сохранением значения
  • didSet вызывается сразу после сохранения значения

Если вы реализуете наблюдатель willSet, то он передает новое значение свойства как константный параметр. Вы можете сами определить ему имя внутри реализации willSet. Если вы не станете указывать новое имя параметра и скобки внутри реализации, то параметр все равно будет доступен через имя параметра по умолчанию newValue.

Аналогично, если вы реализуете наблюдатель didSet, то ему будет передан параметр-константа, содержащий старое значение свойства. Вы можете задать имя параметру, но если вы этого не сделаете, то он все равно будет доступен через имя параметра по умолчанию oldValue.

Заметка

Наблюдатели willSet и didSet суперкласса вызываются, когда свойство устанавливается в инициализаторе подкласса. Они не вызываются в то время, пока класс устанавливает свои собственные свойства, до того, пока не будет вызван инициализатор суперкласса.

Для получения дополнительной информации о делегировании инициализации, см. Делегирование инициализатора для типов значений и Делегирование инициализатора для классовых типов.

Вот пример наблюдателей willSet и didSet в действии. Пример ниже объявляет новый класс StepCounter, который следит за общим числом шагов, которые совершает человек во время прогулки. Этот класс может быть использован с входящими значениями от шагомера или другого счетчика шагов для отслеживания упражнений человека в течении всего рабочего дня.

class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("Вот-вот значение будет равно \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Добавлено \(totalSteps - oldValue) шагов")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// Вот-вот значение будет равно 200
// Добавлено 200 шагов
stepCounter.totalSteps = 360
// Вот-вот значение будет равно 360
// Добавлено 160 шагов
stepCounter.totalSteps = 896
// Вот-вот значение будет равно 896
// Добавлено 536 шагов

Класс StepCounter объявляет свойство totalSteps типа Int. Это хранимое свойство с наблюдателями willSet, didSet.

Как уже говорилось, наблюдатели willSet и didSet вызываются при любом присваивании значения свойством, даже если это значение совпадает со старым.

В этом примере наблюдатель willSet использует пользовательский параметр newTotalSteps для предстоящего нового значения. В этом примере он просто выводит на экран значение, которое будет установлено.

Наблюдатель didSet вызывается после того как totalSteps обновляется. Он сравнивает новое значение totalSteps со старым. Если общее количество шагов увеличилось, то выводится сообщение о том, сколько новых шагов было сделано. Наблюдатель didSet не предоставляет имени пользовательского параметра для старого значения, но по умолчанию это имя oldValue.

Заметка

Если вы передаете свойство, имеющее наблюдателей, в функцию в качестве сквозного параметра, то наблюдатели willSet и didSet всегда вызываются. Это происходит из-за модели памяти копирования copy-in copy-out для сквозных параметров: Значение всегда записывается обратно в свойство в конце функции. Более подробное о сквозных параметрах см. Сквозные параметры.

 

Swift: 
4.0