Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SwiftUI: @State variable never get updated from @Published

I’m trying to trigger an alert when is an error in the model but it never get updated to show the alert:

Here is my implementation in the view:

struct ContentView: View {
    @ObservedObject var viewModel: ViewModel
    @State var showAlert = false
    init() {
        viewModel = ViewModel()
        showAlert = viewModel.showAlert
    }
    var body: some View {
        NavigationView {
            Text("Hello, world!")
                .padding()
        }
        .alert(isPresented: $showAlert) {
            Alert(title: Text("This works"),
                  message: Text("Hello"),
                  dismissButton: .default(Text("got it"))
        )}
    }
}

Here is my models:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class ViewModel: ObservableObject {
    @Published var showAlert = false
    var cancellables = Set<AnyCancellable>()
    
    init() {
        DoSomething.shared.showAlert.sink { _ in
            print("got new Value")
        } receiveValue: {[weak self] value in
            print("value")
            self?.showAlert = value
        }.store(in: &cancellables)
    }
}
class DoSomething {
    let showAlert = PassthroughSubject<Bool, Never>()
    static let shared = DoSomething()
    private init() {
        checkToShowAlert()
    }
    func checkToShowAlert() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
            print("change value")
            self?.showAlert.send(true)
        }
    }
}

Any of you knows why the showAlert variable it never gets updated?

I’ll really appreciate your help

>Solution :

In your current code, you’re setting ContentView‘s showAlert to the ViewModel‘s showAlert at that point in time:

init() {
  viewModel = ViewModel()
  showAlert = viewModel.showAlert //<-- assignment at the time of init
}

Meaning, it’s false at the time of assignment. Because it’s just a Bool getting assigned to another Bool, there’s no mechanism to keep it updated if ViewModel‘s showAlert changes.

The simplest solution is to get rid of your @State variable and observe the @Published property directly:

struct ContentView: View {
    @ObservedObject var viewModel: ViewModel = ViewModel()

    var body: some View {
        NavigationView {
            Text("Hello, world!")
                .padding()
        }
        .alert(isPresented: $viewModel.showAlert) {
            Alert(title: Text("This works"),
                  message: Text("Hello"),
                  dismissButton: .default(Text("got it"))
        )}
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading