Reputation: 10385
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?
}
}
Upvotes: 3
Views: 1094
Reputation: 4450
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!
Upvotes: 4