0

Good evening!

I’m working on a simple project, where I have a view model, which has published boolean value. I would like to show a sheet when this value is set. However, the sheet function uses the Binding type, meanwhile I have the Published type.

Would it be possible to somehow deal with such a case? In case if I will try to deal with it with some callbacks and a State variable in the view object, it will make the architecture more dirty so, I would like to avoid it.


final class ContentViewModel: ObservableObject {
    @Published private(set) var isVisable = false
    func toggleVisability() {
        isVisable.toggle()
    }
} 

struct ContentView: View {
    @StateObject var model = ContentViewModel()

    var body: some View {
        VStack {
            Button("Show") {
                model.toggleVisability()                
            }
            .sheet(isPresented: model.$isVisable, // ERROR: Cannot convert value of type 'Published<Bool>.Publisher' to expected argument type 'Binding<Bool>'
                   onDismiss: { model.toggleVisability() }) {
                Text("Placeholder")
            }
        }
    }
}
Kirill Rud
  • 217
  • 3
  • 9
  • 1
    Remove `private (set)` since the whole point of using Binding is that the value can be updated. So `.sheet` needs to be able to update isVisable – Joakim Danielson Mar 02 '23 at 21:22
  • 1
    Put the dollar sign before model, not on the variable and remove “private set” the sheet has to be able to set it. – lorem ipsum Mar 02 '23 at 21:23
  • Maybe this is a simplified example but otherwise I don’t really see the point of letting the view model handle isVisable so you could move it to the view and make it a @State property. – Joakim Danielson Mar 02 '23 at 21:25

1 Answers1

0

The published variable should be public to set, and binding should be provided for the model (observable object) itself.

final class ContentViewModel: ObservableObject {
    @Published var isVisable = false // CHANGE HERE
    func toggleVisability() {
        isVisable.toggle()
    }
} 

struct ContentView: View {
    @StateObject var model = ContentViewModel()

    var body: some View {
        VStack {
            Button("Show") {
                model.toggleVisability()                
            }
            .sheet(isPresented: $model.isVisable, // CHANGE HERE
                   onDismiss: { model.toggleVisability() }) {
                Text("Placeholder")
            }
        }
    }
}

Many thanks to Joakim Danielson and lorem ipsum.

Kirill Rud
  • 217
  • 3
  • 9