willSet и didSet уведомляют об изменении значения свойства

В разработке приложений для iOS наблюдатели — это объекты, которые уведомляют пользователей о конкретном событии. Наблюдатели за свойствами наблюдают и реагируют на изменения в значении свойства. Они вызываются каждый раз, когда устанавливается значение свойства, даже если новое значение совпадает с текущим значением свойства. Они обеспечивают способ отслеживания изменений свойства.

У нас может быть два следующих наблюдателя для свойства:

  • willSet, который вызывается непосредственно перед сохранением значения. Он поставляется с постоянным параметром, который содержит новое значение, с именем по умолчанию новое значение.
  • didSet, который вызывается сразу после сохранения нового значения. Он поставляется с постоянным параметром, содержащим oldValue, с именем по умолчанию oldValue.

Мы можем переопределить любое из этих имен параметров (newValue, oldValue), но если имя не указано, используются значения по умолчанию.

Согласно Apple, мы можем добавить наблюдателей свойств в следующих местах:

  1. Сохраняемые свойства, определяемые вами
struct Employee {
    var name: String
    var age: Int {
        willSet(newValue) {
            print("\(name) age is set to \(newValue)")
        }
        didSet {
            print("\(name) age changed from \(oldValue) to \(age)")
        }
    }
}

var emp = Employee(name: "Tom", age: 20)
emp.age = 30

// Tom age is set to 30
// Tom age changed from 20 to 30

2. Сохраненные свойства, которые вы наследуете

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
}

class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}

class AutomaticCar: Car {
    override var currentSpeed: Double { // inherit Stored property
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")

// AutomaticCar: traveling at 35.0 miles per hour in gear 4

Для унаследованного свойства вы добавляете наблюдателя свойства, переопределяя это свойство в подклассе.

3.Вычисляемые свойства, которые вы наследуете

class Shape {
    var width = 0.0
    var height = 0.0
    
    var area: Double {
        get {
            return width * height
        }
        set {
            self.width = sqrt(newValue)
            self.height = sqrt(newValue)
        }
    }
}

class Rectangle: Shape {
    override var area: Double {
        didSet {
            print("Old value is \(oldValue)")
        }
        willSet {
            print("New value is \(newValue)")
        }
    }
}

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

struct Rectangle {
    var width = 0.0
    var height = 0.0
    
    var area: Double {
        get {
            return width * height
        }
        set {
            self.width = sqrt(newValue)
            self.height = sqrt(newValue)
        }
    }
}

var rectAngle = Rectangle(width: 10, height: 10)
print(rectAngle.area)

Начиная с Swift 5.3, наблюдатели за свойствами теперь можно прикреплять к свойствам lazy.

class GreetingClass {
    lazy var greeting: String = "Hi" {
        willSet(newValue) {
            print(newValue)
        }
       didSet {
        print(oldValue)
      }
    }
}

var obj = GreetingClass()
obj.greeting = "Hello"

Ключевые моменты, которые следует помнить наблюдателю за недвижимостью

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

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

Заключение

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

Спасибо за прочтение. Если у вас есть какие-либо комментарии, вопросы или рекомендации, не стесняйтесь публиковать их в разделе комментариев ниже! 👇. Пожалуйста, поделитесь и хлопайте 👏👏 если вам понравился этот пост.