UIHostingController question...

I have a SwiftUI view that works as expected in a full SwiftUI context. But I now need to use it in a UIViewController. It mostly works, but I'm trying to expose an @State var out to the viewController, and it only ever returns the initial value. Any guidance for how best to pass out this @State var? I could make it be a binding, but in my pure SwiftUI code, it works fine as @State (ie EditorView's container view does not need to know about sliderVal)

thanks, in advance, for any suggestions

import SwiftUI
import UIKit
class ViewController: UIViewController {
    var host: UIHostingController<EditorView>?
    override func viewDidLoad() {
        super.viewDidLoad()
        host = .init(rootView: EditorView())
        guard let host = host else { return }
        addChild(host)
        host.view.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(host.view)
        host.didMove(toParent: self)
    }
    @IBAction func helloTapped(sender: UIButton) {
        guard let sliderValue = host?.rootView.sliderVal else { return }
        print("UIKit sliderValue: \(sliderValue)")
    }
}

struct EditorView: View {
    @State var sliderVal: Double
    init(sliderVal: Double? = nil) {
        _sliderVal = State(initialValue: sliderVal ?? 7)
    }
    var body: some View {
        VStack {
            Slider(value: $sliderVal, in: 1...10)
            Text("sliderVal: \(sliderVal)")
        }
    }
}

(NOTE: in order to see this code snippet in action you will need to create a button in the storyboard and link it to helloTapped)

Answered by DTS Engineer in 776484022

@mikeTheDad You should review Using SwiftUI with UIKit sample project to learn how to incorporate SwiftUI views into a UIKit app. Using the @ObservedObject property wrapper as @JimmyCricket suggested in this case ensures that SwiftUI automatically refresh the view when any of the @Published properties of the ObservableObject change, and also allows a binding to be created so that SwiftUI can write back changes to that property when the slider value changes

State shouldn't be directly accessed outside of the view that they’re declared in (unless passed to a subview) and it’s actually best to declare them private—as you can see, trying to access it outside of the view hierarchy in causes some unexpected behavior.

As an alternative, you can pass in an observable object which holds the state outside of the view safely, and instead update and check a variable on that for the value.

@mikeTheDad You should review Using SwiftUI with UIKit sample project to learn how to incorporate SwiftUI views into a UIKit app. Using the @ObservedObject property wrapper as @JimmyCricket suggested in this case ensures that SwiftUI automatically refresh the view when any of the @Published properties of the ObservableObject change, and also allows a binding to be created so that SwiftUI can write back changes to that property when the slider value changes

UIHostingController question...
 
 
Q