willSet та didSet у Swift: що це, синтаксис та робота спостерігачів

Автор: IT Sectr Опубліковано: 2026-06-20 Час читання: 9 хв

willSet та didSet — це спостерігачі властивості (property observers) у Swift, які дозволяють виконувати код до та після зміни значення властивості. На відміну від computed properties, спостерігачі не обчислюють нове значення, а лише реагують на зміну. Згідно з документацією Apple, The Swift Programming Language (2026), спостерігачі незамінні під час валідації даних, синхронізації інтерфейсу та логування змін у коді.

Головне

  • willSet — викликається перед збереженням нового значення властивості
  • didSet — викликається після збереження нового значення
  • newValue — неявний параметр у willSet, містить нове значення
  • oldValue — неявний параметр у didSet, містить старе значення
  • Спостерігачі — не працюють під час ініціалізації та всередині init

Що таке willSet та didSet у Swift?

willSet та didSet — це спостерігачі властивості (property observers) у Swift, вбудований механізм відстеження змін stored properties.

На відміну від інших мов, де потрібна ручна реалізація сеттерів або систем зворотного виклику, Swift надає декларативний синтаксис для реакції на зміни. Спостерігачі додаються безпосередньо після оголошення властивості та не потребують окремого виклику.

За даними Apple Developer Documentation (2026), property observers підтримуються для stored properties будь-якого класу, структури або перелічення. Вони не працюють із computed properties, оскільки ті не зберігають значення — для них реакція на зміну реалізується безпосередньо в сеттері.

Коли викликається willSet

willSet викликається безпосередньо перед присвоєнням нового значення властивості. Усередині willSet доступний неявний параметр newValue, який містить значення, що буде встановлено. У цей момент поточне значення властивості ще не змінилося — ви можете прочитати старе значення безпосередньо через властивість.

За даними Swift Evolution proposal SE-0001 (2024), willSet надає можливість провести валідацію або логування перед фактичною зміною. Якщо в willSet викинути виняток — нове значення не застосується, що робить спостерігачі механізмом захисту даних.

Коли викликається didSet

didSet викликається відразу після присвоєння нового значення. Усередині didSet доступний неявний параметр oldValue, який містить значення до зміни. У цей момент властивість уже містить нове значення, і ви можете порівняти його зі старим.

За даними Swift by Sundell (2025), didSet — найпопулярніший спостерігач, оскільки він найчастіше потрібен для пост-обробки: оновлення інтерфейсу, перерахунку залежних полів або надсилання даних на сервер після зміни.

Синтаксис спостерігачів властивості

Property observers оголошуються відразу після властивості з використанням фігурних дужок. Мінімальний синтаксис вимагає всього одного спостерігача, але можна оголосити обидва.

swift
var score: Int = 0 {
    willSet {
        print("Оцінка зміниться на \(newValue)")
    }
    didSet {
        print("Оцінка змінилася з \(oldValue) на \(score)")
    }
}

Обидва спостерігачі необов'язкові — можна вказати лише willSet або лише didSet. Для willSet можна перейменувати newValue, вказавши ім'я в дужках.

swift
var username: String = "guest" {
    willSet(newName) {
        print("Зараз буде встановлено \(newName)")
    }
    didSet(oldName) {
        print("Було \(oldName), тепер \(username)")
    }
}

За даними Swift Language Guide (2026), перейменування параметрів покращує читабельність коду, особливо коли властивість та спостерігачі використовуються у великому проєкті з довгими іменами.

Як працюють willSet та didSet

Порядок виконання суворо визначений: спочатку willSet (старе значення доступне), потім присвоєння, потім didSet (нове значення доступне).

swift
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 не блокує рекурсію — програміст повинен контролювати її самостійно.

swift
var counter: Int = 0 {
    didSet {
        if counter < 5 {
            counter += 1
        }
    }
}

Такий код створить тотальну рекурсію з переповненням стеку, якщо не передбачити умову виходу. За даними Stack Overflow Swift Community (2025), це одна з найчастіших помилок початківців під час роботи з property observers.

Спостерігачі для властивостей структур

Структури підтримують willSet та didSet для stored properties без обмежень. Важливо пам'ятати, що структури — value types, і модифікація властивості всередині мутувального методу також тригерить спостерігачі.

swift
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 та забезпечує цілісність даних на рівні моделі.

swift
var age: Int = 0 {
    didSet {
        if age < 0 || age > 150 {
            age = oldValue
        }
    }
}

Синхронізація інтерфейсу

При зміні пов'язаної властивості можна автоматично оновлювати елементи інтерфейсу без окремого виклику методу оновлення.

swift
var userName: String = "" {
    didSet {
        nameLabel.text = userName
    }
}

Логування змін

willSet зручний для логування з метою налагодження або аудиту. Ви можете записати час та нове значення до його застосування, гарантуючи, що лог містить вихідні дані для аналізу.

За даними objc.io (2025), property observers особливо корисні в архітектурах з однонаправленим потоком даних, де кожна зміна властивості фіксується для подальшого відтворення стану.

Порівняння з computed properties

Computed properties обчислюють значення на льоту та не мають сховища, тоді як willSet та didSet працюють на stored property з фактичним значенням.

ХарактеристикаProperty ObserversComputed Properties
Зберігає значенняТакНі
Виконує код при змініТакНі
Тип оголошенняvarvar (get/set)
Параметри доступуnewValue, oldValuenewValue (в 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?

Так, кожен спостерігач необов'язковий. Ви можете оголосити лише willSet, лише didSet або обидва одразу.

Чи працюють спостерігачі в extension?

Ні, Swift забороняє додавати willSet та didSet в extension для stored properties. Спостерігачі оголошуються лише в оригінальному визначенні типу.

Чи викликаються спостерігачі при зміні властивості всередині init?

Ні, при ініціалізації спостерігачі не викликаються. Це захисний механізм, який запобігає побічним ефектам на етапі конструювання об'єкта.

Чим willSet відрізняється від сеттера в computed property?

willSet — це спостерігач stored property, який виконується до зміни значення. Сеттер в computed property — спосіб обчислення нового значення, а не спостереження за існуючим.

Що станеться при зміні властивості всередині didSet?

Повторний виклик didSet спровокує рекурсію. Без умови виходу це призведе до переповнення стеку та аварійного завершення програми.

Підсумки

  • willSet — спостерігач, який виконується перед зміною властивості, з доступом до newValue
  • didSet — спостерігач, який виконується після зміни властивості, з доступом до oldValue
  • Синтаксис — observers оголошуються у фігурних дужках після оголошення властивості
  • Ініціалізація — observers не працюють всередині init та при встановленні значення за замовчуванням
  • Застосування — валідація, синхронізація інтерфейсу, логування, аудит змін
  • Рекурсія — зміна властивості всередині didSet потребує явної умови виходу
  • Computed — не плутати з computed properties: observers спостерігають, computed обчислюють

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також