带部分的 SwiftUI 动态列表布局不正确

SwiftUI dynamic List with Sections does not Layout correctly

我正在尝试创建一个分为多个部分的简单动态列表。 (SwiftUI iOS13 Xcode11 测试版 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")
            }
        }
    }
}

这会按预期显示一个包含 header 节和页脚

的漂亮列表

但是当我尝试从这样的动态列表中执行此操作时:

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 行的列表。部分 header、所有内容单元格和页脚都水平组合成一行。

我错过了什么?

List 一组项目似乎使其错误地将 Section 视为单一视图。

您可能应该为此提交雷达,但与此同时,这将为您提供您正在寻找的行为:

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

只是对上面的正确答案进行了小修正。自

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

不像我那样编译,所以这个编译并像一个魅力一样工作:

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

虽然上述解决方案适用于静态数据,但我 运行 遇到了不同的情况。在我的例子中, "mygroups" 等效项在列表首次组成时为空。在 .onAppear{} 块中,我构建了组。

建立组后,我更新了@State,列表因这条老朋友消息而崩溃:

'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).'

我从一个空数组变成了一个有两个部分的数组。我认为列表还没有准备好进行如此复杂的动态更改(除非我还没有找到 API)。

我可能会做的是在 List 有机会看到它之前尝试构建它。

将列表嵌入 VStack 解决了我的问题。