I am truly at a loss here. I use @Published vars and view models all the time and have never run into this issue.
I am using a simple ternary to change what is shown on the view so I can have a progress indicator when something is loading. The only way I have gotten this view to update and show the indicator is when I take the VM out of the equation and use an @State private var (which I do not want to do). Even the onChange modifier in the view that should simply print to console when the @Published bool in the VM changes is not seeing anything.
Here's a simple example:
struct TestView: View {
@StateObject var viewModel: ViewModel
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .center) {
VStack {
Button("Loading Test") {
viewModel.testLoading()
}
}
.onChange(of: viewModel.showProgress) { _ in
print("View Showing: \(viewModel.showProgress ? "True" : "False")")
}
.disabled(viewModel.showProgress)
.blur(radius: viewModel.showProgress ? 3 : 0)
VStack {
Text("Loading...")
ProgressView()
.progressViewStyle(CircularProgressViewStyle())
.scaleEffect(1.5)
}
.frame(width: geometry.size.width / 3,
height: geometry.size.height / 5)
.background(Color.secondary.colorInvert())
.foregroundColor(Color.primary)
.cornerRadius(20)
.opacity(viewModel.showProgress ? 1 : 0)
}
}
}
}
extension TestView {
@MainActor
class ViewModel: ObservableObject {
@Published var showProgress: Bool = false
func testLoading() {
self.showProgress = true
print("Show Progress: \(self.showProgress ? "True" : "False")")
sleep(5)
self.showProgress = false
print("Show Progress: \(self.showProgress ? "True" : "False")")
}
}
}
The console output from the function in the VM is showing that it is changing the @Published var properly, but no changes to that variable are seen in the view, except for the disabled modifier. You cannot tap anything in the view when the @Published var is true, and as soon as it becomes false, whatever you tried to tap activates (I would also like to prevent this behavior, but that's another question).
With this simple test, you should be able to tap the Loading Test button text and the showProgress @Published var is changed to true for 5 seconds and then back to false. When it's true, the view should be blurred and the progress indicator should be shown.