[英]SwiftUI List selection binding updates twice on every click, if wrapped in NavigationView (macOS)
Given the below code, I made a strange observation (on macOS).鉴于下面的代码,我做了一个奇怪的观察(在 macOS 上)。 If a List is wrapped in a NavigationView I suddenly get two updates per click on a row (one on mouseDown - aka holding the mouse click down and not releasing it, one on mouseUp - aka releasing the mouse click).如果 List 包含在 NavigationView 中,我突然每次点击一行都会获得两个更新(一个在 mouseDown 上 - 也就是按住鼠标点击而不释放它,一个在 mouseUp - 也就是释放鼠标点击)。 This doesn't happen on a plain simple list, or if it's wrapped in an HStack instead.这不会发生在简单的列表上,或者如果它被包装在 HStack 中。 Does anyone know why and how I can control / change this behavior?有谁知道我为什么以及如何控制/改变这种行为?
See HStack version in action:查看 HStack 版本:
See NavigationView version in action:查看 NavigationView 版本:
struct ContentView: View {
@State var selection: Set<Int> = []
var body: some View {
List(0..<20, selection: Binding(get: {
self.selection
}, set: { val in
print("set \(val)")
self.selection = val
})) { idx in
Text("\(idx)")
}
Color.red
Color.green
Color.blue
}
}
// Wrapped in a HStack, 1 update per row selection is triggered, as expected!
struct HStackVersion: View {
var body: some View {
HStack(spacing:0.0) {
ContentView()
}
}
}
// Wrapped in a NavigationView, 2 updates per row selection are triggered??
struct NavigationViewVersion: View {
var body: some View {
NavigationView {
ContentView()
}
}
}
The screenshot below shows the stacktrace for a breakpoint in the setter showing that SwiftUI.ListCoreCoordinator
is setting the binding twice.下面的屏幕截图显示了设置器中断点的堆栈跟踪,显示SwiftUI.ListCoreCoordinator
设置了两次绑定。 I've seen a similar problem with Map
here .我在这里看到了与Map
类似的问题。 I'm not sure if duplicate calls to binding setters is part of their design or not but it understandably could be, given that SwiftUI coalesces all state changes into a single call to body
.我不确定对绑定设置器的重复调用是否是他们设计的一部分,但它可以理解,因为 SwiftUI 将所有状态更改合并到对body
的单个调用中。
If you'd like to work around the issue then I would suggest going with the more standard onChange
modifier instead of that custom Binding
, onChange
is only called once for the new value, eg如果您想解决这个问题,那么我建议您使用更标准的onChange
修饰符而不是那个自定义Binding
, onChange
只为新值调用一次,例如
struct MacListProbView: View {
@State var selection: Set<Int> = []
var body: some View {
List(0..<20, selection: $selection) { idx in
Text("\(idx)")
}
.onChange(of: selection) { newSelection in
print("set \(newSelection)")
}
}
}
struct MacListProbViewNav: View {
var body: some View {
NavigationView {
MacListProbView()
Color.red // note it's more efficient to have these here because they are not affected by the selection value.
Color.green
Color.blue
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.