如何定义一个接受任意数据元素并产生“某些”视图的闭包?

时间:2019-12-14 03:55:15

标签: swiftui

我正在构建一个显示字符串集合的自定义视图,但是我想扩展它以接受一个闭包,该闭包将使这些字符串中的每个字符串呈现不同的外观,可能不是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的对象。

1 个答案:

答案 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)
        }
    }
}