Is it possible to make a UIViewRepresentable
view which takes a ViewBuilder
argument work with dynamic content such as ForEach
loops?
I have the following UIViewRepresentable
view which I’m using to drop down to UIKit
and get some custom UIScrollView
behaviour:
struct CustomScrollView<Content:View>: UIViewRepresentable {
private let content: UIView
private let scrollView = CustomUIScrollView()
init(@ViewBuilder content: () -> Content) {
self.content = UIHostingController(rootView: content()).view
self.content.backgroundColor = .clear
}
func makeUIView(context: Context) -> UIView {
scrollView.addSubview(content)
// ...
return scrollView
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
This works fine with static content as follows:
var body: some View {
CustomScrollView {
VStack {
ForEach(1..<50) { number in
Text(String(number))
}
}
}
}
But it fails with dynamic content, showing a blank view:
var body: some View {
CustomScrollView {
VStack {
ForEach(self.numbers) { number in
Text(String(number))
}
}
}
}
I understand that this is because when makeUIView()
is called my dynamic data is empty, and it is later filled or updated. I evaluate my UIViewRepresentable
’s content
at init, and don’t update it in updateUIView()
.
How do you go about updating dynamic child content in updateUIView()
? I tried capturing the @ViewBuilder
parameter as an @escaping
closure and evaluating it every time updateUIView()
is called, which seems like the right solution (albeit inefficient?), but no luck so far.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…