I have an ExpandingView like this:
struct ExpandingView: View {
@State var isExpanded = false
var body: some View {
RoundedRectangle(cornerRadius: 16.0)
.fill(Color.accentColor.opacity(0.1))
.overlay {
Button("Toggle expand") {
withAnimation {
isExpanded.toggle()
}
}
}
.frame(height: isExpanded ? 500 : 100)
}
}
struct ContentView: View {
var body: some View {
ExpandingView()
.border(Color.red)
.padding()
}
}
Result:
This works fine. However, due to performance reasons, I am experimenting with embedding ExpandingView within a intermediary UIHostingController instead of having it inline. This way, I have more control over how it's rendered.
struct WrapperHostingControllerRepresentable<Content: View>: UIViewControllerRepresentable {
@ViewBuilder var content: Content
func makeUIViewController(context: Context) -> UIHostingController<Content> {
UIHostingController(rootView: content)
}
func updateUIViewController(_ uiViewController: UIHostingController<Content>, context: Context) {
uiViewController.rootView = content
}
func sizeThatFits(_ proposal: ProposedViewSize, uiViewController: UIHostingController<Content>, context: Context) -> CGSize? {
let canvas = CGSize(width: proposal.width ?? 0, height: 5000)
let size = uiViewController.sizeThatFits(in: canvas)
print("Calculating size: \(size)")
return size
}
}
struct ContentView: View {
var body: some View {
WrapperHostingControllerRepresentable {
ExpandingView()
}
.border(Color.red)
.padding()
}
}
Here's the result:
As you can see, the red border is not recalculated and Calculating size: (370.0, 100.0) is printed only once in the console. How do I get the UIViewRepresentable to resize along with its contents?



