I am not quite sure I understand what is going on here as I am experimenting with an EnvironmentObject in SwiftUI.
I recreated my problem with a small example below, but to summarize: I have a ContentView
, ContentViewModel
, and a StateController
. The ContentView
holds a TextField that binds with the ContentViewModel
. This works as expected. However, if I update a value in the StateController
(which to me should be completely unrelated to the ContentViewModel
) the text in the TextField is rest.
Can someone explain to me why this is happening, and how you could update a state on an EnvironmentObject without having SwiftUI redraw unrelated parts?
App.swift
@main
struct EnvironmentTestApp: App {
@ObservedObject var stateController = StateController()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(stateController)
}
}
}
ContentView.swift
struct ContentView: View {
@ObservedObject private var viewModel = ContentViewModel()
@EnvironmentObject private var stateController: StateController
var body: some View {
HStack {
TextField("Username", text: $viewModel.username)
Button("Update state") {
stateController.validated = true
}
}
}
}
ContentViewModel.swift
class ContentViewModel: ObservableObject {
@Published var username = ""
}
StateController.swift
class StateController: ObservableObject {
@Published var validated = false
}
Like lorem-ipsum pointed out, you should use @StateObject.
A good rule of thumb is to use @StateObject
every time you init a viewModel, but use @ObservedObject
when you are passing in a viewModel that has already been init.