Site icon AppTractor

Избегайте ошибок SwiftUI с ViewModel

Когда я впервые перешёл с 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-разработчик:

Эта ментальная модель спасла меня.

Давайте писать лучший код SwiftUI — и не просто приложения, которые «работают», а приложения, которые мы понимаем.

Источник

Exit mobile version