我正在构建一个显示字符串集合的自定义视图,但是我想扩展它以接受一个闭包,该闭包将使这些字符串中的每个字符串呈现不同的外观,可能不是Text
视图。例如,这是我的原始代码:
struct MyCollectionView : View {
var data : [String]
var body : some View {
ZStack {
ForEach(0..<data.count, id: \.self) { string in
Text(string) // <- will try to invoke the closure here
}
}
}
}
但是现在我想注入一个“ renderer”闭包,该闭包将接受一个字符串并产生一个视图,如下所示:
struct MyCollectionView : View {
typealias CellRenderer = (String)->View
var cellRenderer : CellRenderer = { string in // compiler error on CellRenderer: "Protocol 'View'
// can only be used as a generic constraint because it has Self or associated type requirements"
Text(string)
} // default implementation
var data : [String]
var body : some View {
ZStack {
ForEach(0..<data.count, id: \.self) { string in
self.cellRenderer(string) // <- trying to invoke the cell renderer
}
}
}
}
如何声明这种关闭?也许它不应该是一个闭包,而是一个在给定字符串的情况下会产生some View
的对象。
答案 0 :(得分:1)
这是一种可能的方法。与Xcode 11.2,iOS 13.2兼容。
struct MyCollectionView<Data, Cell>: View where Data: Hashable, Cell: View {
typealias CellRenderer = (Data) -> Cell
var data : [Data]
var cellRenderer : CellRenderer
init(_ data: [Data], @ViewBuilder cellRenderer: @escaping CellRenderer) {
self.data = data
self.cellRenderer = cellRenderer
}
var body : some View {
ZStack {
ForEach(data, id: \.self) { value in
self.cellRenderer(value)
}
}
}
}
struct MyCollectionView_Previews: PreviewProvider {
static var previews: some View {
MyCollectionView(["one", "two"]) { value in
Text(value)
}
}
}