Please IGNORE the post above 👆, as I've realised the issue is just about onChange and viewA's position in the stack.
The following code snippet is revised to demonstrate the issue, or my confusion.
Only logs in View B's onChange closure are printed if you use the view ViewAInTheMiddle, then go to View B and tap the button to toggle that flag. Both logs in View A and View B's onChange closure are printed if you use the view ViewAAsRoot. However, logs in View A's onReceive closure are always printed regardless.
I know I might be misusing onChange in this scenario, but could someone please point out where the misuse is? Thanks.
class ViewModel: ObservableObject {
@Published var flag = false
}
struct ViewAInTheMiddle: View {
var body: some View {
NavigationStack {
NavigationLink {
ViewA()
} label: {
Text("Goto viewA")
}
}
}
}
struct ViewAAsRoot: View {
var body: some View {
NavigationStack {
ViewA()
}
}
}
struct ViewA: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
NavigationLink(destination: {
ViewB(viewModel: viewModel)
}, label: {
Text("goto ViewB")
})
.onReceive(viewModel.$flag) { newValue in
print("ViewA receiving - flag: \(newValue)")
}
.onChange(of: viewModel.flag) { newValue in
print("ViewA - flag: \(newValue)")
}
}
}
struct ViewB: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Button {
viewModel.flag.toggle()
} label: {
Text("Toggle the flag")
}
.onChange(of: viewModel.flag) { newValue in
print("ViewB - flag: \(newValue)")
}
}
}