当 @State var 基于 Picker 选择发生变化时,一个视图不会重新呈现
Posted
技术标签:
【中文标题】当 @State var 基于 Picker 选择发生变化时,一个视图不会重新呈现【英文标题】:One view does not rerender when @State var changes based on Picker selection 【发布时间】:2020-01-31 16:48:54 【问题描述】:尝试使用 SwiftUI 构建一个简单的 MacOS 应用。我有一个包含绑定到 State var 的 Picker 的视图。作为健全性检查,我添加了一个文本视图(矮人一号和卷...itemName),它也应该随着选取器的变化而变化。他们会这样做,但我要重新渲染的视图(FileList)没有。
我怀疑这与我尝试将新的 FileSystemItem(内部类)传递给 FileList 的方式有关。就像 FilePanel 重新渲染时一样,volumeSelection 回到 0,然后应用状态。所以我的问题是我似乎缺少关于这些数据应该如何流动的基本概念。我再次浏览了 WWDC 信息并阅读了其他文章,但我没有看到答案。
所需的行为是更改选择器上的选择应该导致新的 FileSystemItem 显示在 FileList 视图中。什么是让这种情况发生的正确方法?更笼统地说,当 Picker 选择发生变化时,如何让子视图显示新数据?
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)
【问题讨论】:
我想帮忙,但我不能“只是复制”你的代码并运行它,这并不好玩...... :( 这不是代码运行时发生的问题。问题中描述了该行为。问题在于 SwiftUI 中完成将新值推送(或使其可用)到子视图的正确方法是什么。 【参考方案1】:@State
是拥有视图的私有状态,FileList
永远不会看到任何变化。
如果VolumesModel
是将FileList.item
转换为绑定(in-out-state)的简单结构可能已经工作(调用者在将@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,我认为从长远来看这是我需要的。谢谢!以上是关于当 @State var 基于 Picker 选择发生变化时,一个视图不会重新呈现的主要内容,如果未能解决你的问题,请参考以下文章
iOS 15 SwiftUI 3 Picker 绑定在更改@State 值后不起作用
创建一个@State var 区域,即基于两个@State var 宽度,一个@State var 高度