Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a Publishable property in a view controller, pass it to a SwiftUI View and listen to changes inside view controller?

This is what I am trying to achieve:

class MyVC: UIViewController {
    @State var myBoolState: Bool = false

    private var subscribers = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        myBoolState.sink { value in .... }.store(in:&subscribers)
    }

    func createTheView() {
        let vc = UIHostingController(rootView: MySwiftUIView(myBoolState: $myBoolState))
        self.navigationController!.pushViewController(vc, animated: true)
    }
}

struct MySwiftUIView: View {
    @Binding var myBoolState: Bool

    var body: some View {
          Button(action: {
              myBoolState = true
          }) {
              Text("Push Me")
          }

    }

}

But the above of course does not compile.

So the question is: can I somehow declare a published property inside a view controller, pass it to a SwiftUI View and get notified when the SwiftUI view changes its value?

like image 769
Joris Mans Avatar asked Nov 02 '25 08:11

Joris Mans


1 Answers

The @State wrapper works (by design) only inside SwiftUI view, so you cannot use it in view controller. Instead there is ObsevableObject/ObservedObject pattern for such purpose because it is based on reference types.

Here is a demo of possible solution for your scenario:

import Combine

class ViewModel: ObservableObject {
    @Published var myBoolState: Bool = false
}

class MyVC: UIViewController {
    let vm = ViewModel()
    
    private var subscribers = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        vm.$myBoolState.sink { value in
            print(">> here it goes")
        }.store(in:&subscribers)
    }

    func createTheView() {
        let vc = UIHostingController(rootView: MySwiftUIView(vm: self.vm))
        self.navigationController!.pushViewController(vc, animated: true)
    }
}

struct MySwiftUIView: View {
    @ObservedObject var vm: ViewModel

    var body: some View {
          Button(action: {
            vm.myBoolState = true
          }) {
              Text("Push Me")
          }
    }
}
like image 71
Asperi Avatar answered Nov 04 '25 02:11

Asperi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!