3

I'm trying to change below code(1.) to MVVM architecture(2.) but can't figure out how to bind objects.

I think the problem is FirstView only pass value but not actually a Binding Object, I tried some different ways but always stuck on don't know how to assign Binding Object to @Published.

Could somebody please give a few hints?

  1. (Works fine)
struct FirstView: View {
    @State var showSecondView = false

    var body: some View {
        Button(action: {
            self.showSecondView.toggle()
        }) {
            Text("Show second view")
        }
        .sheet(isPresented: $showSecondView) {
            SecondView(showSecondView: self.$showSecondView)
        }
    }
}
struct SecondView: View {
    @Binding var showSecondView: Bool

    var body: some View {
        Button(action: {
            self.showSecondView.toggle()
        }) {
            Text("Dismiss")
        }
    }
}
  1. (MVVM)
struct FirstView: View {
    @ObservedObject var vm = FirstViewModel()

    var body: some View {
        Button(action: {
            self.vm.showSecondView.toggle()
        }) {
            Text("Show second view")
        }
        .sheet(isPresented: $vm.showSecondView) {
            SecondView2(vm: SecondViewModel(showSecondView: self.vm.showSecondView))
        }
    }
}

class FirstViewModel: ObservableObject {
    @Published var showSecondView = false
}
struct SecondView: View {
    @ObservedObject var vm: SecondViewModel

    var body: some View {
        Button(action: {
            self.vm.showSecondView.toggle()
        }) {
            Text("Dismiss")
        }
    }
}

class SecondViewModel: ObservableObject {
    @Published var showSecondView: Bool

    //Right here, i'm not sure how to bind 'showSecondView' from FirstView
    init(showSecondView: Bool) {
        self.showSecondView = showSecondView
    }
}

1 Answer 1

4

You can pass directly the Binding<Bool> to the second VM but in this way, there's no need to have @Published var and it also doesn't need to be ObservableObject and marked as @ObservedObject. There might be a better solution to this.

struct FirstView: View {
    @ObservedObject var vm = FirstViewModel()

    var body: some View {
        Button(action: {
            self.vm.showSecondView.toggle()
        }) {
            Text("Show second view")
        }
        .sheet(isPresented: $vm.showSecondView) {
            SecondView(vm: SecondViewModel(showSecondView: self.$vm.showSecondView))
        }
    }
}

class FirstViewModel: ObservableObject {
    @Published var showSecondView = false
}

struct SecondView: View {
    var vm: SecondViewModel

    var body: some View {
        Button(action: {
            self.vm.showSecondView.wrappedValue.toggle()
        }) {
            Text("Dismiss")
        }
    }
}

class SecondViewModel {
    var showSecondView: Binding<Bool>

    init(showSecondView: Binding<Bool>) {
        self.showSecondView = showSecondView
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, really helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.