ahe*_*eze 3 generics ios swift swift-keypath swiftui
我使用 aForEach来显示数组的内容,然后通过检查元素索引手动显示每个元素之间的分隔线。这是我的代码:
struct ContentView: View {\n let animals = ["Apple", "Bear", "Cat", "Dog", "Elephant"]\n\n var body: some View {\n VStack {\n /// array of tuples containing each element\'s index and the element itself\n let enumerated = Array(zip(animals.indices, animals))\n ForEach(enumerated, id: \\.1) { index, animal in\n Text(animal)\n\n /// add a divider if the element isn\'t the last\n if index != enumerated.count - 1 {\n Divider()\n .background(.blue)\n }\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n结果:
\n
这是可行的,但我想要一种在各处自动添加分隔线的方法,而无需Array(zip(animals.indices, animals))每次都编写分隔线。这是我到目前为止所拥有的:
struct ForEachDividerView<Data, Content>: View where Data: RandomAccessCollection, Data.Element: Hashable, Content: View {\n var data: Data\n var content: (Data.Element) -> Content\n\n var body: some View {\n let enumerated = Array(zip(data.indices, data))\n ForEach(enumerated, id: \\.1) { index, data in\n\n /// generate the view\n content(data)\n\n /// add a divider if the element isn\'t the last\n if let index = index as? Int, index != enumerated.count - 1 {\n Divider()\n .background(.blue)\n }\n }\n }\n}\n\n/// usage\nForEachDividerView(data: animals) { animal in\n Text(animal)\n}\nRun Code Online (Sandbox Code Playgroud)\n这非常有效,隔离了所有样板zip代码并且仍然得到相同的结果。然而,这只是因为animals是 s 的数组String,它符合Hashable\xe2\x80\x94 如果我的数组中的元素不符合Hashable,它将不起作用:
struct Person {\n var name: String\n}\n\nstruct ContentView: View {\n let people: [Person] = [\n .init(name: "Anna"),\n .init(name: "Bob"),\n .init(name: "Chris")\n ]\n\n var body: some View {\n VStack {\n\n /// Error! Generic struct \'ForEachDividerView\' requires that \'Person\' conform to \'Hashable\'\n ForEachDividerView(data: people) { person in\n Text(person.name)\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n这就是为什么 SwiftUIForEach附带了一个额外的初始化程序 ,init(_:id:content:)它采用自定义键路径来提取 ID。我想在我的 中利用这个初始化程序ForEachDividerView,但我无法弄清楚。这是我尝试过的:
struct ForEachDividerView<Data, Content, ID>: View where Data: RandomAccessCollection, ID: Hashable, Content: View {\n var data: Data\n var id: KeyPath<Data.Element, ID>\n var content: (Data.Element) -> Content\n\n var body: some View {\n let enumerated = Array(zip(data.indices, data))\n\n /// Error! Invalid component of Swift key path\n ForEach(enumerated, id: \\.1.appending(path: id)) { index, data in\n\n content(data)\n\n if let index = index as? Int, index != enumerated.count - 1 {\n Divider()\n .background(.blue)\n }\n }\n }\n}\n\n\n/// at least this part works...\nForEachDividerView(data: people, id: \\.name) { person in\n Text(person.name)\n}\nRun Code Online (Sandbox Code Playgroud)\n我尝试使用将appending(path:)第一个关键路径(从 中提取元素)与第二个关键路径(从元素中enumerated获取属性)组合起来,但我得到了。HashableInvalid component of Swift key path
ForEach即使元素不符合 ,如何在 a 的元素之间自动添加分隔线Hashable?
简单的方法
struct ContentView: View {
let animals = ["Apple", "Bear", "Cat", "Dog", "Elephant"]
var body: some View {
VStack {
ForEach(animals, id: \.self) { animal in
Text(animal)
if animals.last != animal {
Divider()
.background(.blue)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
通常,动物体内的类型必须是可识别的。在这种情况下,代码将被修改为。
if animals.last.id != animal.id {...}
Run Code Online (Sandbox Code Playgroud)
这将避免任何同等的要求/实施
使用评论中提到的文章,我构建了以下内容。它采用一组视图并在它们之间放置一个分隔线。
当视图不是由 a 生成时ForEach,尤其是当有条件地删除一个或多个视图时(例如使用语句if),这也很有用。
struct Divided<Content: View>: View {
var content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
_VariadicView.Tree(DividedLayout()) {
content
}
}
struct DividedLayout: _VariadicView_MultiViewRoot {
@ViewBuilder
func body(children: _VariadicView.Children) -> some View {
let last = children.last?.id
ForEach(children) { child in
child
if child.id != last {
Divider()
}
}
}
}
}
struct Divided_Previews: PreviewProvider {
static var previews: some View {
VStack {
Divided {
Text("Alpha")
Text("Beta")
Text("Gamma")
}
}
.previewDisplayName("Vertical")
HStack {
Divided {
Text("Alpha")
Text("Beta")
Text("Gamma")
}
}
.previewDisplayName("Horizontal")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2090 次 |
| 最近记录: |