Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Binding contained within UIViewControllerRepresentable does not get updated

Tags:

swiftui

I have a UIHostingController contained in a UIViewControllerRepresentable that holds a reference to a binding. When the binding changes, updateUIViewController is called, but the underlying view is not automatically re-rendered. How can I signal to the embedded UIHostingController that it needs to update its content?

Following is a simplified version of the scenario. Note that when the stepper changes, the first Text automatically updates, but the text contained within the PassthroughView UIViewControllerRepresentable does not automatically see its content get re-rendered.

import SwiftUI

struct ContentView: View {
    @State var number = 99

    var body: some View {
        VStack {
            Stepper("Stepper", value: $number)
            Text("Direct Value: \(number)")
            PassthroughView {
                Text("Passthrough Value: \(number)")
            }
            Spacer()
        }.font(.headline)
    }
}

struct PassthroughView<V: View> : UIViewControllerRepresentable {
    typealias UIViewControllerType = UIHostingController<V>
    let content: V

    init(@ViewBuilder _ content: () -> V) {
        self.content = content()
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<PassthroughView<V>>) -> UIViewControllerType {
        UIViewControllerType(rootView: content)
    }

    func updateUIViewController(_ controller: UIViewControllerType, context: UIViewControllerRepresentableContext<PassthroughView<V>>) {
        // this is called when the binding changes;
        // how to tell the UIHostingController to re-render?
    }
}
like image 237
marcprux Avatar asked Feb 21 '26 07:02

marcprux


1 Answers

The following code will work as desired:

I am not sure if it is good practice since I am not very familiar with UIKit.

struct PassthroughView<V: View> : UIViewControllerRepresentable {
    typealias UIViewControllerType = UIHostingController<V>
    let content: V

    init(@ViewBuilder _ content: () -> V) {
        self.content = content()
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<PassthroughView<V>>) -> UIViewControllerType {
        UIViewControllerType(rootView: content)
    }

    func updateUIViewController(_ controller: UIViewControllerType, context: UIViewControllerRepresentableContext<PassthroughView<V>>) {
        // this is called when the binding changes;
        // how to tell the UIHostingController to re-render?
        controller.rootView = content
    }
}

struct ContentView: View {

    @State var number = 99

    var body: some View {
        VStack {
            Stepper("Stepper", value: $number)
            Text("Direct Value: \(number)")
            PassthroughView {
                Text("Passthrough Value: \(number)")
            }
            Spacer()
        }.font(.headline)
    }

}

I hope this helps!

like image 107
krjw Avatar answered Feb 23 '26 12:02

krjw



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!