如何避免在SwiftUI中的回调闭包中使用"AnyView"类型的擦除



我正在尝试创建基于ListScrollView的表视图,并使用共享的基本视图。我目前的尝试使用了一种基于构建器的方法,但需要使用AnyView类型擦除的闭包。

我的目标是避免使用AnyView类型的擦除,以提高性能、可扩展性和设计。

到目前为止,我使用泛型类型参数重新设计的尝试都失败了。

下面的简化(有效(代码示例只显示了一个String列,但抓住了基本的挑战。(实际上,这些是具有各种数据类型、专用格式化程序、修饰符等的多列表。(

import SwiftUI
struct ContentView: View {
let data = ["a", "b", "c", "d"]
var body: some View {
HStack {
ListTable(title: "My List", data: data)
ScrollTable(title: "My Scroll", data: data)
}
}
}
struct ListTable<T: Hashable>: View {
var title: String, data: [T]
var body: some View {
BaseTable() { header, row in
VStack {
header(title)
List(data, id: .self) { row($0) }
}
}
}
}
struct ScrollTable<T: Hashable>: View {
var title: String, data: [T]
var body: some View {
BaseTable() { header, row in
VStack {
header(title)
ScrollView { ForEach(data, id: .self) { row($0) } }
}
}
}
}
struct BaseTable<Content: View, T: Hashable>: View {
typealias HBuilder = (String) -> AnyView
typealias RBuilder = (T) -> AnyView
var builder: (@escaping HBuilder, @escaping RBuilder) -> Content
var body: some View {
// NOTE this is where I'd like to avoid type-erasure to AnyView
builder({ AnyView( Text("Header ($0)") )},
{ AnyView( Text("Row (String(describing: $0))") ) })
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View { ContentView() }
}

两个相关的问题并没有完全提供解决方案:

  • 65810765-如何创建一个结构参数,该参数是带输入的闭包,在SwiftUI中返回some View而不是AnyView
  • 64655195-如何避免在将SwiftUI视图作为参数传递给函数时将其强制转换为AnyView

我自己的问题有一个有效的答案。

为行创建一个"包装器"视图,该视图将提供行生成器闭包中使用的显式类型:

// new 'wrapper' view, which can contain Text, LazyVGrid, etc.
struct RowView<T: Hashable>: View {
var value: T
var body: some View {
Text("Row (String(describing: value))")
}
}
// update to original BaseTable
struct BaseTable<Content: View, T: Hashable>: View {
typealias HBuilder = (String) -> Text
typealias RBuilder = (T) -> RowView<T>
var builder: (@escaping HBuilder, @escaping RBuilder) -> Content
var body: some View {
builder({ Text("Header ($0)") },
{ RowView<T>(value: $0) })
}
}

感谢评论者!

最新更新