为什么@Published 更新Text 但不更新List?

Why @Published updates Text but doesn't update List?

我不明白为什么 Text 更新而 List 不更新。

我有一个带有 @Published 的模型,它是一个日期数组。 还有一种方法可以根据日期生成文本。

这是一个简化版本:

class DataModel: NSObject, ObservableObject {
    
    @Published var selectedDates: [Date] = []

    func summary() -> String {
        var lines: [String] = []
        for date in selectedDates.sorted().reversed() {
            let l = "\(someOtherStuff) \(date.dateFormatted)"
            lines.append(l)
        }
        return lines.joined(separator: "\n")
    }

}

然后我在我的视图中显示了这段文字。这是一个简化版本:

struct DataView: View {

    @ObservedObject var model: DataModel

    var body: some View {
        ScrollView {
            Text(model.summary())
        }
    }

}

有效:当用户从视图中的 UI 添加日期到 model.selectedDates 时,摘要文本已正确更新。


现在我想用行列表替换文本。

我改方法:

    func summary() -> [String] {
        var lines: [String] = []
        for date in selectedDates.sorted().reversed() {
            let l = "\(someOtherStuff) \(date.dateFormatted)"
            lines.append(l)
        }
        return lines
    }

并更改视图:

    var body: some View {
        ScrollView {
            List {
                ForEach(model.summary(), id: \.self) { line in
                    Text(line)
                }
            }
        }
    }

但这不起作用:列表中根本没有文本,当用户向 model.selectedDates 添加日期时,它永远不会更新。

我做错了什么?

我能够在 SO 上找到 到之前的 post,这可能是您问题的解决方案。当您说列表中根本没有文本时,您是否进行了调试以验证这一点,或者只是屏幕上没有显示任何数据?

当我复制你的代码片段并摆弄它时,看起来列表中确实有列表试图在屏幕上显示的数据,但列表的框架被覆盖了滚动视图。将所有内容嵌套在 GeometryReader 中并为 List 提供框架大小,为程序提供了您正在寻找的功能。

为您的数据使用 ScrollView 或 List。如果一个列表有多个值,它会自动变成一个可滚动的列表。所以,我相信您可以完全删除 ScrollView。

这是一个固定的工作变体(有一些复制 - 所以您需要将其调整回您的项目)。

测试 Xcode 12.1 / iOS 14.1

class DataModel: NSObject, ObservableObject {
    
    @Published var selectedDates: [Date] = []
    
    func summary() -> [String] {
        var lines: [String] = []
        for date in selectedDates.sorted().reversed() {
            let l = "someOtherStuff \(date)"
            lines.append(l)
        }
        return lines
    }
    
}

struct DataView: View {
    
    @ObservedObject var model: DateDataModel = DataModel()
    
    var body: some View {
        VStack {
            Button("Add") { model.selectedDates.append(Date())}
            List {
                ForEach(model.summary(), id: \.self) { line in
                    Text(line)
                }
            }
        }
    }
    
}