温馨提示:本文翻译自stackoverflow.com,查看原文请点击:ios - One view does not rerender when @State var changes based on Picker selection
ios macos swift swiftui

ios - @State var基于Picker选择更改时,一个视图不会重新呈现

发布于 2020-04-06 00:27:07

尝试使用SwiftUI构建一个简单的MacOS应用。我有一个视图,其中包含绑定到State var的Picker。作为健全性检查,我添加了一个文本视图(矮人视图和卷... itemName),该视图也应随着Picker的更改而更改。它们确实可以,但是我要重新渲染的视图(文件列表)却没有。

我怀疑这与我想将新的FileSystemItem(内部类)传递给FileList的方式有关。就像在FilePanel重新渲染时一样,volumeSelection返回0,然后再应用状态。所以我的问题是,我似乎缺少有关该数据如何流动的基本概念。我再次浏览了WWDC信息,并正在阅读其他文章,但没有找到答案。

所需的行为是更改选择器上的选择,这应该导致在FileList视图中显示一个新的FileSystemItem。什么是使这种情况发生的正确方法?更笼统地说,当选择器选择更改时,如何使子视图显示新数据?

struct FilePanel: View 
{
    @State var volumeSelection = 0
    @State var pathSelection = 0

    var volumes = VolumesModel() //should be passed in?
    var dwarves = ["Schlumpy","Wheezy","Poxxy","Slimy","Pervy","Drooly"]

    var body: some View {
        VStack {
            Picker(selection: $volumeSelection, label:
                Text("Volume")
                , content: {
                    ForEach (0 ..< volumes.count()) {
                        Text(self.volumes.volumeAtIndex(index: $0).itemName).tag($0)
                    }
            })

            FileList(item:volumes.volumeAtIndex(index: volumeSelection)).frame(minWidth: CGFloat(100.0), maxHeight: .infinity)
            Text(dwarves[volumeSelection])
            Text(volumes.volumeAtIndex(index: volumeSelection).itemName)

        }
    }
 }

struct FileList: View {
    @State var item : FileSystemItem

    var body: some View {
        VStack {
        List(item.childItems){fsi in
            FileCell(expanded:false, item: fsi)
        }
        Text(item.itemName)
        }
    }
}

查看更多

提问者
vagrant
被浏览
72
nine stones 2020-02-01 11:39

@State是拥有视图私有的状态,FileList永远不会看到任何变化。

如果将VolumesModel一个简单的结构FileList.item变成绑定(输入输出状态)可能已经起作用了(调用者使用将其@State传递给依赖项时仍需要将其变成绑定$):

struct FileList: View {
  @Binding var item : FileSystemItem
  ...
}

但是,感觉好像VolumesModel是一个具有成员数组的更复杂的对象。

在这种情况下,以上内容将无法满足要求:

  • VolumesModel 需要成为一个班级采用 ObservableObject
  • VolumesModel的重要成员需要可绑定的包装器(@Published
  • FileList.item应该变成@ObservedObject(而不是@State或@Binding)
  • FilePanel.volumes也要@ObservedObject包裹

希望能帮助或至少指引您正确的方向。