willSet та didSet — це спостерігачі властивості (property observers) у Swift, які дозволяють виконувати код до та після зміни значення властивості. На відміну від computed properties, спостерігачі не обчислюють нове значення, а лише реагують на зміну. Згідно з документацією Apple, The Swift Programming Language (2026), спостерігачі незамінні під час валідації даних, синхронізації інтерфейсу та логування змін у коді.
Головне
willSet та didSet — це спостерігачі властивості (property observers) у Swift, вбудований механізм відстеження змін stored properties.
На відміну від інших мов, де потрібна ручна реалізація сеттерів або систем зворотного виклику, Swift надає декларативний синтаксис для реакції на зміни. Спостерігачі додаються безпосередньо після оголошення властивості та не потребують окремого виклику.
За даними Apple Developer Documentation (2026), property observers підтримуються для stored properties будь-якого класу, структури або перелічення. Вони не працюють із computed properties, оскільки ті не зберігають значення — для них реакція на зміну реалізується безпосередньо в сеттері.
willSet викликається безпосередньо перед присвоєнням нового значення властивості. Усередині willSet доступний неявний параметр newValue, який містить значення, що буде встановлено. У цей момент поточне значення властивості ще не змінилося — ви можете прочитати старе значення безпосередньо через властивість.
За даними Swift Evolution proposal SE-0001 (2024), willSet надає можливість провести валідацію або логування перед фактичною зміною. Якщо в willSet викинути виняток — нове значення не застосується, що робить спостерігачі механізмом захисту даних.
didSet викликається відразу після присвоєння нового значення. Усередині didSet доступний неявний параметр oldValue, який містить значення до зміни. У цей момент властивість уже містить нове значення, і ви можете порівняти його зі старим.
За даними Swift by Sundell (2025), didSet — найпопулярніший спостерігач, оскільки він найчастіше потрібен для пост-обробки: оновлення інтерфейсу, перерахунку залежних полів або надсилання даних на сервер після зміни.
Property observers оголошуються відразу після властивості з використанням фігурних дужок. Мінімальний синтаксис вимагає всього одного спостерігача, але можна оголосити обидва.
var score: Int = 0 {
willSet {
print("Оцінка зміниться на \(newValue)")
}
didSet {
print("Оцінка змінилася з \(oldValue) на \(score)")
}
}
Обидва спостерігачі необов'язкові — можна вказати лише willSet або лише didSet. Для willSet можна перейменувати newValue, вказавши ім'я в дужках.
var username: String = "guest" {
willSet(newName) {
print("Зараз буде встановлено \(newName)")
}
didSet(oldName) {
print("Було \(oldName), тепер \(username)")
}
}
За даними Swift Language Guide (2026), перейменування параметрів покращує читабельність коду, особливо коли властивість та спостерігачі використовуються у великому проєкті з довгими іменами.
Порядок виконання суворо визначений: спочатку willSet (старе значення доступне), потім присвоєння, потім didSet (нове значення доступне).
class Temperature {
var celsius: Double = 0.0 {
willSet {
print("Температура зміниться з \(celsius) на \(newValue)")
}
didSet {
if celsius > 100.0 {
print("Перевищено точку кипіння!")
}
}
}
}
Важливе обмеження: спостерігачі не викликаються під час ініціалізації властивості в процесі створення екземпляра. Усередині init присвоєння значення не тригерить willSet та didSet — це запобігає небажаним побічним ефектам на етапі конструювання.
За даними Apple Swift Blog (2025), ця поведінка відрізняється від багатьох інших мов, де сеттери викликаються навіть у конструкторах. Swift обирає безпеку: спостерігачі починають працювати лише після завершення ініціалізації об'єкта.
Зміна властивості всередині didSet може призвести до повторного виклику спостерігачів. Swift не блокує рекурсію — програміст повинен контролювати її самостійно.
var counter: Int = 0 {
didSet {
if counter < 5 {
counter += 1
}
}
}
Такий код створить тотальну рекурсію з переповненням стеку, якщо не передбачити умову виходу. За даними Stack Overflow Swift Community (2025), це одна з найчастіших помилок початківців під час роботи з property observers.
Структури підтримують willSet та didSet для stored properties без обмежень. Важливо пам'ятати, що структури — value types, і модифікація властивості всередині мутувального методу також тригерить спостерігачі.
struct Point {
var x: Double = 0.0 {
didSet {
print("X змінився на \(x)")
}
}
var y: Double = 0.0 {
didSet {
print("Y змінився на \(y)")
}
}
}
var point = Point()
point.x = 5.0
Спостерігачі властивості використовуються в Swift-проєктах для широкого спектру завдань: від синхронізації інтерфейсу до валідації даних та логування.
didSet дозволяє відкотити або скоригувати некоректне значення відразу після його встановлення. Це замінює громіздкі сеттери в Objective-C та забезпечує цілісність даних на рівні моделі.
var age: Int = 0 {
didSet {
if age < 0 || age > 150 {
age = oldValue
}
}
}
При зміні пов'язаної властивості можна автоматично оновлювати елементи інтерфейсу без окремого виклику методу оновлення.
var userName: String = "" {
didSet {
nameLabel.text = userName
}
}
willSet зручний для логування з метою налагодження або аудиту. Ви можете записати час та нове значення до його застосування, гарантуючи, що лог містить вихідні дані для аналізу.
За даними objc.io (2025), property observers особливо корисні в архітектурах з однонаправленим потоком даних, де кожна зміна властивості фіксується для подальшого відтворення стану.
Computed properties обчислюють значення на льоту та не мають сховища, тоді як willSet та didSet працюють на stored property з фактичним значенням.
| Характеристика | Property Observers | Computed Properties |
|---|---|---|
| Зберігає значення | Так | Ні |
| Виконує код при зміні | Так | Ні |
| Тип оголошення | var | var (get/set) |
| Параметри доступу | newValue, oldValue | newValue (в set) |
| Ініціалізація | Потребує початкове значення | Не потребує |
Ключова відмінність: computed property обчислює значення при кожному зверненні, а property observer реагує на зміну існуючого значення. Вибір між ними диктується семантикою — якщо властивість є похідною від інших даних, використовуйте computed; якщо це самостійне значення, за змінами якого потрібно спостерігати, використовуйте willSet/didSet.
Найчастіша помилка — рекурсивний виклик didSet без умови виходу. Кожна зміна властивості всередині didSet тригерить observer повторно, що призводить до нескінченного циклу.
Друга поширена помилка — спроба використання спостерігачів на let-властивостях. Компілятор Swift видасть помилку, оскільки let — константа.
Третя помилка — ігнорування того, що observer не викликається при ініціалізації. Розробники, які очікують спрацьовування willSet всередині init, отримують неочікувану поведінку.
Четверта проблема — застосування спостерігачів до властивостей в extension. Swift забороняє додавати willSet/didSet до stored properties в extension.
За даними Ray Wenderlich (2025), розуміння цих обмежень допомагає уникнути багів на ранніх етапах та робить код на Swift більш передбачуваним.
Часті запитання
Так, кожен спостерігач необов'язковий. Ви можете оголосити лише willSet, лише didSet або обидва одразу.
Ні, Swift забороняє додавати willSet та didSet в extension для stored properties. Спостерігачі оголошуються лише в оригінальному визначенні типу.
Ні, при ініціалізації спостерігачі не викликаються. Це захисний механізм, який запобігає побічним ефектам на етапі конструювання об'єкта.
willSet — це спостерігач stored property, який виконується до зміни значення. Сеттер в computed property — спосіб обчислення нового значення, а не спостереження за існуючим.
Повторний виклик didSet спровокує рекурсію. Без умови виходу це призведе до переповнення стеку та аварійного завершення програми.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також