SwiftUI : Как @Observable заменяет @Published и ObservableObject
🔍 Введение
С выходом iOS 17 Apple представила новый макрос @Observable, который радикально упрощает работу с состоянием в SwiftUI. В этой статье мы разберём:
- Как @Observable заменяет связку ObservableObject + @Published
- Как теперь работать с @Environment
- Как создавать биндинги через @Bindable
- Какие подводные камни есть у withObservationTracking
🧱 Было: ObservableObject и @Published
✅ Стало: @Observable (iOS 17+)
⚠ При использовании @Observable мы сохраняем объект с помощью @State, чтобы он не сбрасывался при перерисовке View.
📦 Передача через @Environment
Было: @EnvironmentObject
Стало: .environment() + @Environment(Type.self)
SwiftUI сам определяет, какой тип объекта нужно искать в environment.
🔄 Проблема с биндингами
@Environment не даёт доступ к $player.score, и это вызывает ошибку:
✅ Решение: @Bindable
🧠 Внутренности: withObservationTracking
Новая система работает через withObservationTracking:
Но! onChange вызывается до изменения (поведение willSet). Чтобы получить новое значение, нужен DispatchQueue.main.async.
В отличие от Combine, нельзя просто подписаться на свойство и использовать .debounce, .map и другие операторы.
🔚 Заключение
Новый макрос @Observable делает SwiftUI ещё более декларативным. Он упрощает архитектуру, снижает количество обвязки и избавляет от зависимости на Combine. Но если вы работаете вне SwiftUI или с асинхронными задачами — ObservableObject пока может быть удобнее.