是否可以制作一个UIViewRepresentable
的视图,该视图使用ViewBuilder
参数处理动态内容,例如ForEach
循环?
我有以下UIViewRepresentable
视图,可用于下拉至UIKit
并获得一些自定义的UIScrollView
行为:
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) {}
}
此方法可用于静态内容,如下所示:
var body: some View {
CustomScrollView {
VStack {
ForEach(1..<50) { number in
Text(String(number))
}
}
}
}
但是它无法显示动态内容,显示空白视图:
var body: some View {
CustomScrollView {
VStack {
ForEach(self.numbers) { number in
Text(String(number))
}
}
}
}
我了解这是因为调用makeUIView()
时,我的动态数据为空,后来被填充或更新。我在初始化时评估了UIViewRepresentable
的{{1}},并且没有在content
中对其进行更新。
您如何在updateUIView()
中更新动态子内容?我尝试将updateUIView()
参数捕获为@ViewBuilder
闭包,并在每次调用@escaping
时对其进行评估,这似乎是正确的解决方案(尽管效率不高?),但到目前为止还没有运气。 / p>
答案 0 :(得分:1)
以下内容可能会有所帮助。目前尚不清楚CustomUIScrollView
的表现如何(可能存在问题),但是使用标准UIScrollView
可以与动态ForEach一起使用。使用Xcode 11.4 / iOS 13.4进行了测试
struct CustomScrollView<Content:View>: UIViewRepresentable {
private let content: UIView
private let scrollView = UIScrollView()
init(@ViewBuilder content: () -> Content) {
self.content = UIHostingController(rootView: content()).view
self.content.backgroundColor = .clear
}
func makeUIView(context: Context) -> UIView {
content.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(content)
let constraints = [
content.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
content.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
content.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
content.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
content.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
]
scrollView.addConstraints(constraints)
return scrollView
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
struct TestCustomScrollView: View {
private var items = Array(repeating: "Test", count: 50)
var body: some View {
CustomScrollView {
VStack {
ForEach(Array(items.enumerated()), id: \.0) { i, item in
Text("\(item) - \(i)")
}
}
}
}
}
答案 1 :(得分:1)
@ViewBuilder的评估失败,因为您在此处突变了该结构的错误副本
func updateUIView(_ uiView: UIView, context: Context) {}
您应该直接使用uiView
来更改content()
的子视图
更新后的答案:删除了带有协调器的解决方案,因为在某些情况下,该解决方案无法按预期运行