Когда я впервые перешёл с UIKit на SwiftUI, одной из самых неприятных ошибок, с которыми я столкнулся, была следующая:
Моя ViewModel постоянно неожиданно ресетилась.
Казалось, это происходит случайно, пока я не понял разницу между @StateObject и @ObservedObject.
Если у вас та же проблема, позвольте мне объяснить проще.
Если вы создаёте ViewModel внутри View — используйте
@StateObject
Вот что нужно сделать:
struct CounterView: View {
@StateObject var viewModel = CounterViewModel()
var body: some View {
Text("Count: \(viewModel.count)")
}
}
Это означает:
«SwiftUI, я создаю этот объект — пожалуйста, сохраните его и управляйте его жизненным циклом».
SwiftUI создаст его один раз и сохранит при перерисовке.
❌ Чего не следует делать: не используйте @ObservedObject для создания модели.
Эта ошибка выглядит так:
@ObservedObject var viewModel = CounterViewModel() // ❌
Это сообщает SwiftUI:
«Я ожидаю, что это будет внедрено, а не создано здесь». (Вы правильно поняли, попробуйте запомнить DI — внедрение зависимостей).
И SwiftUI рассматривает его как временного наблюдателя, поэтому каждый раз при перерисовке вашего представления он может заново создавать объект и сбрасывать ваше состояние.
✅ Используйте @ObservedObject при передаче ViewModel.
Предположим, ViewModel получена от родительского объекта:
struct ParentView: View {
var body: some View {
CounterView(viewModel: sharedModel)
}
}
struct CounterView: View {
@ObservedObject var viewModel: CounterViewModel
var body: some View {
Text("Count: \(viewModel.count)")
}
}
В этом случае @ObservedObject идеально подходит. Вы не создаёте, а просто наблюдаете.
Правило, которому я следую как iOS-разработчик:
- Создаёте? Используйте
@StateObject - Получаете? Используйте
@ObservedObject
Эта ментальная модель спасла меня.
Давайте писать лучший код SwiftUI — и не просто приложения, которые «работают», а приложения, которые мы понимаем.

