I'm wanting to use a SwiftUI View as content for a child UIView (which in my app would be inside UIViewController) by passing SwiftUI. However the SwiftUI View doesn't respond to state changes once embedded inside UIView.
I created the simplified version of my code below that has the issue. When tapping the Text View embedded inside the EmbedSwiftUIView the outer Text View at the top VStack updates as expected but the Text View embedded inside the EmbedSwiftUIView does not update its state.
struct ProblemView: View {
@State var count = 0
var body: some View {
VStack {
Text("Count is: \(self.count)")
EmbedSwiftUIView {
Text("Tap to increase count: \(self.count)")
.onTapGesture {
self.count = self.count + 1
}
}
}
}
}
struct EmbedSwiftUIView<Content:View> : UIViewRepresentable {
var content: () -> Content
func makeUIView(context: UIViewRepresentableContext<EmbedSwiftUIView<Content>>) -> UIView {
let host = UIHostingController(rootView: content())
return host.view
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<EmbedSwiftUIView<Content>>) {
}
}
In case we have to modify state when another state is known, we can encapsulate all those states in ObservableObject and use onReceive to check the state we want to act on. Modifying state during view update, this will cause undefined behavior.
SwiftUI calls the makeUIView method once to let you instantiate the UIKit view. For any redraw, SwiftUI will call into the updateUIView method to let you update the underlying UIKit view.
SwiftUI works seamlessly with the existing UI frameworks on all Apple platforms. For example, you can place UIKit views and view controllers inside SwiftUI views, and vice versa.
Update view or view controller in updateUIView
or updateUIViewController
function. In this case, using UIViewControllerRepresentable
is easier.
struct EmbedSwiftUIView<Content: View> : UIViewControllerRepresentable {
var content: () -> Content
func makeUIViewController(context: Context) -> UIHostingController<Content> {
UIHostingController(rootView: content())
}
func updateUIViewController(_ host: UIHostingController<Content>, context: Context) {
host.rootView = content() // Update content
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With