尝试使用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)
}
}
}
@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
包裹希望能帮助或至少指引您正确的方向。
我发现@State正在发生类似的情况,因此感谢您的确认。我一直在看ObservableObject,但是对于我试图完成的(看似)简单的事情来说,这似乎有点过头了。但是我想这是我应该追求的。感谢您的建议,不胜感激!
您是正确的,FileList中的@State是错误的。您还让我看看ObservableObject,从长远来看,我认为这是我所需要的。谢谢!