SwiftUI动态列表与分区不正确布局。

36
我正在尝试创建一个简单的动态列表,分成几个部分。(SwiftUI iOS13 Xcode11 beta 2)
一个简单的静态示例可以是:
struct StaticListView : View {
    var body: some View {
        List {
            Section(header: Text("Numbers"), footer: Text("...footer...")) {
                Text("1")
                Text("2")
                Text("3")
            }
            Section(header: Text("Letters"), footer: Text("...footer...")) {
                Text("a")
                Text("b")
                Text("c")
            }
        }
    }
}

这将按预期显示一个带有节标题和页脚的漂亮列表

但是当我尝试从动态列表中进行此操作时,会出现以下情况:

struct TestData: Identifiable {
    var id = UUID()
    var title: String
    var items: [String]
}

struct ListView : View {
    let mygroups = [
        TestData(title: "Numbers", items: ["1","2","3"]),
        TestData(title: "Letters", items: ["A","B","C"]),
        TestData(title: "Symbols", items: ["€","%","&"])
    ]
    var body: some View {
        List (mygroups) { gr in
            Section(header: Text(gr.title),
                    footer: Text("...footer...") ) {
                ForEach(gr.items.identified(by: \.self)) { item in
                    Text(item)
                }
            }
        }
    }
}
结果是一个只有3行的列表。节标题、所有内容单元格和页脚都水平合并成为一行。 我错过了什么?
4个回答

67

将一组项赋给 List 似乎会导致它错误地将 Section 视为单个视图。

你可能应该为此提交一个 Radar,但同时,这将为你提供你要寻找的行为:

struct ListView : View {
    let mygroups = [
        TestData(title: "Numbers", items: ["1","2","3"]),
        TestData(title: "Letters", items: ["A","B","C"]),
        TestData(title: "Symbols", items: ["€","%","&"])
    ]

    var body: some View {
        List {
            ForEach(mygroups) { gr in
                Section(header: Text(gr.title),
                        footer: Text("...footer...") ) {
                            ForEach(gr.items.identified(by: \.self)) { item in
                                Text(item)
                            }
                }
            }
        }
    }
}


2
非常感谢!问题完全解决了。我刚刚在一个包含超过8000行和1000个部分的表格上尝试了一下,效果非常好! - Bo Frese
1
我简直不敢相信这个生效了 - 完全不知道为什么默认行为是将每个部分列为一行... - Quinn
这很棒 - 我发现当你添加搜索和删除等功能时,事情开始变得混乱。 - DogCoffee

15

上面的答案正确,只需做一个小修正。因为

ForEach(gr.items.identified(by: \.self)) { item in
                            Text(item)
                        }

对于我来说,它无法编译,所以这个可以编译并且运行得很好:

ForEach(gr.items, id: \.self, content: { item in
                            Text(item)
                        })

8
这应该是对现有答案的编辑,而不是另一个独立的答案。 - grg

1
虽然上述解决方案适用于静态数据,但我遇到了不同的情况。在我的情况下,“mygroups”等效项在首次组合列表时为空。在.onAppear {}块中,我构建了分组。
一旦分组建立起来,我就会更新@State,但是List会因为这个老朋友消息而崩溃:
'NSInternalInconsistencyException',reason:'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (2), plus or minus the number of sections inserted or deleted (2 inserted, 0 deleted).'
我从一个空数组变成了有两个部分的数组。我认为List还没有准备好处理如此复杂的动态更改(除非有我尚未找到的API)。
我可能会尝试在List有机会看到它之前先构建它。

是的 - 在将数据源交给List之前构建您的列表数据源是正确的方法。目前,我的List在构建后不需要更改,但我想知道如果有添加和删除项目的操作,List会有多稳定。对于任何试图显示动态组合部分列表的人:首先将您的数据源构建为数组的数组 - 不要使用字典 - 然后按照这里的解决方案中的代码创建List。 - P. Ent
我也遇到了这个问题。找到任何解决方案了吗? - Zappel

-2

将列表嵌入VStack中,问题得到了解决。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接