在尝试 Swift UI 4 中新的 NavigationStack
的过程中,我发现当状态改变时,navigationDestination()
返回的目标视图没有得到更新。请参阅下面的代码。
struct ContentView: View {
@State var data: [Int: String] = [
1: "One",
2: "Two",
3: "Three",
4: "Four"
]
var body: some View {
NavigationStack {
List {
ForEach(Array(data.keys).sorted(), id: \.self) { key in
NavigationLink("\(key)", value: key)
}
}
.navigationDestination(for: Int.self) { key in
if let value = data[key] {
VStack {
Text("This is \(value)").padding()
Button("Modify It") {
data[key] = "X"
}
}
}
}
}
}
}
问题重现步骤:
运行代码并点击列表中的第一项。这将带您进入该项的详细视图。
详细视图显示了该项的值。它还有一个修改该值的按钮。单击该按钮。您会发现详细视图中的值不会更改。
我通过在不同位置设置断点来调试问题。我的观察结果:
当我点击按钮时,
List
中的代码被执行。这是预期的。但是传递给
navigationDestination()
的闭包未被执行,这解释了为什么详细视图没有更新。
是否有人知道这是一个bug还是预期行为? 如果这不是一个bug,那么我该如何编程以更新详细视图中的值?
顺便说一下,如果我回到根视图并再次点击第一项以进入其详细视图,则传递给navigationDestination()
的闭包将被执行,并且详细视图将正确显示修改后的值。
navigationDestination
仅在激活NavigationLink
时调用,而不是在State
更改时调用。”我不认为那是正确的。 - rayxdata
值已经过期。然而,正如我在原始问题中所描述的那样,我在闭包中设置了断点,但当我按下“修改”按钮时,它没有被触发。所以这个闭包没有被调用。嗯...对我来说,一个视图修饰符如何确定是否调用它的闭包参数似乎是个谜。 - rayxdata
,那是错的。我相信实际上被捕获的是一个不可变的self
副本(整个结构体的值)。这个self
稍后会被“Modify It”按钮动作闭包修改。但是,如果State
包装器将实际值存储在内存中相同的位置,我认为旧的self
和新的self
应该共享相同的data
值,因此根本没有这样的问题。所以似乎data
在内存中的实际位置一直在改变?这是我不知道的SwiftUI实现细节。 - rayx