I have a NavigationView which navigates to a first detail view. From this first detail view it navigates to a second detail view. In this second detail view I compose the UI observing a detailViewModel enum that stores the state: notRequested, loading and loaded. It works fine until I add the @Environment(.dismiss) var dismiss in the first detail view, when this occurs the view model enum changes but the UI is not repainted. Here is the sample code:
import SwiftUI
struct TestParentView: View {
var body: some View {
NavigationView {
Button {
} label: {
NavigationLink {
TestDetailView()
} label: {
Text("Go to detail")
}
}
}
}
}
struct TestDetailView: View {
// THIS LINE PROVOKES TestDetail2View NOT UPDATING VIEW
@Environment(\.dismiss) var dismiss
var body: some View {
Button {
} label: {
NavigationLink {
TestDetail2View()
} label: {
Text("Go to detail 2")
}
}
}
}
struct TestDetail2View: View {
@ObservedObject var testDetail2VM = TestDetail2VM()
var body: some View {
content
}
@ViewBuilder
private var content: some View {
switch testDetail2VM.state {
case .notRequested:
Text("")
.onAppear {
Task {
await testDetail2VM.getData()
}
}
case .loading:
Text("Loading data...")
case .loaded:
Text("LOADED VIEW!")
}
}
}
enum TestDetailState {
case notRequested
case loading
case loaded
}
final class TestDetail2VM: ObservableObject {
@Published var state = TestDetailState.notRequested
@MainActor func getData() async {
state = .loading
try! await Task.sleep(nanoseconds: 2_000_000_000)
state = .loaded
}
}
I've observed several things:
The problem only occurs if the view is the second (or more) view navigated. This problem doesn't occur if there are two vies in the navigation stack
If the view model has the annotation @StateObject instead of @ObservedObject, the problem doesn't occur (not a solution due to maybe an observed object is needed in that view)