带有部分的 SwiftUI 动态列表无法正确布局

Posted

技术标签:

【中文标题】带有部分的 SwiftUI 动态列表无法正确布局【英文标题】:SwiftUI dynamic List with Sections does not Layout correctly 【发布时间】:2019-11-03 12:43:09 【问题描述】:

我正在尝试创建一个简单的动态列表,分组为多个部分。 (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 行的列表。 Section header、所有内容单元格和页脚都水平组合成一行。

我错过了什么?

【问题讨论】:

【参考方案1】:

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)
                            
                
            
        
    

【讨论】:

非常感谢!彻底解决了问题。我只是在一个有 1000 多个部分的 8000 多行的表上试了一下。像魅力一样工作! 我不敢相信这行得通 - 不知道为什么默认行为是将每个部分列为一行... 这太棒了 - 我发现当您添加搜索和删除等功能时,事情开始下降。【参考方案2】:

只是对上述正确答案的一个小修复。自从

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

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

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

【讨论】:

这应该是对现有答案的编辑,而不是单独的答案【参考方案3】:

虽然上述解决方案适用于静态数据,但我遇到了不同的情况。就我而言,第一次组成列表时,“mygroups”等效项为空。在 .onAppear 块中,我构建了组。

一旦组建立起来,我会更新@State,列表会因这条老朋友消息而崩溃:

'NSInternalInconsistencyException',原因:'无效更新:无效的节数。更新后表视图中包含的节数(2)必须等于更新前表视图中包含的节数(2),加上或减去插入或删除的节数(2插入,0已删除)。'

我从一个空数组变成了一个包含两个部分的数组。我认为 List 还没有为如此复杂的动态变化做好准备(除非我还没有找到 API)。

我可能会在列表有机会看到它之前尝试构建它。

【讨论】:

所以是的 - 在将其交给 List 之前构建您的列表数据源是可行的方法。现在,我的 List 构建后不需要更改,但我想知道如果您有添加和删除项目的操作,List 有多稳定。对于任何试图显示动态组合的部分列表的人:首先将您的数据源构建为数组数组 - 不要使用 Dictionary - 然后按照此处解决方案中的代码创建列表。 我正遇到这个问题。找到任何解决方案了吗?【参考方案4】:

将 List 嵌入 VStack 为我解决了这个问题。

【讨论】:

以上是关于带有部分的 SwiftUI 动态列表无法正确布局的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:导航在带有部分的列表中无法正常工作

.ondelete 带有部分的 SwiftUI 列表

SwiftUI 列表未使用 ForEach 正确更新

带有 SwiftUI 的 Apple Watch 上列表项的背景 [重复]

带有 @Binding 控件的 SwiftUI 动态列表

SwiftUI:“@Published”属性更改时未刷新“带有组的动态列表”