更改 @Binding 结构的值会导致子视图在父视图更新时被关闭
Changing the value of a struct that is @Binding causes the child view to be dismissed as the parent view updates
我的目标是拥有一组结构,当点击单个项目时,会进行更改并将其传递到父视图,但不会自动关闭我的子视图。我真的不确定为什么子视图会自动关闭以及如何防止它。这是我的 ContentView
代码
import SwiftUI
struct Person: Hashable {
var name: String = ""
}
struct ContentView: View {
@State private var patients: [Person]
init() {
var temp: [Person] = []
for index in 0 ..< 3 {
temp.append(Person(name: "\(index)"))
}
patients = temp
}
var body: some View {
NavigationView {
VStack(spacing: 40) {
ForEach($patients, id:\.self) { $patient in
NavigationLink("\(patient.name)") {
ChangeNameView(patient: $patient)
}
}
}
}
}
}
struct ChangeNameView: View {
@Binding var patient: Person
var body: some View {
Button {
patient.name = "New Name"
} label: {
Text("Set New Name")
}
}
}
点击名称将按预期调出子视图。然后点击按钮更改名称,但会立即关闭视图。
问题是因为 Person
是 Hashable
(它只使用 name
属性)并且对于你的 ForEach
,你'重新使用 \.self
作为 id
.
SwiftUI 的 ForEach
使用 id:
参数来跟踪列表中的哪个元素。因为您正在使用 \.self
然后 更改 ChangeNameView
中那个元素的 name
,它看起来不再像同一个元素并且 SwiftUI 删除了层次结构中的子视图(因为旧视图不再存在于列表中)。
一个解决方案是使用真正的 Identifiable
元素,其中 id
是唯一的并且在您更改 name
时不会更新:
struct Person: Hashable, Identifiable { //<-- Here
var id = UUID() //<-- Here
var name: String = ""
}
struct ContentView: View {
@State private var patients: [Person]
init() {
var temp: [Person] = []
for index in 0 ..< 3 {
temp.append(Person(name: "\(index)"))
}
patients = temp
}
var body: some View {
NavigationView {
VStack(spacing: 40) {
ForEach($patients) { $patient in //<-- Here -- when the items are Identifiable, it's essentially like saying `id: \.id`
NavigationLink("\(patient.name)") {
ChangeNameView(patient: $patient)
}
}
}
}
}
}
我的目标是拥有一组结构,当点击单个项目时,会进行更改并将其传递到父视图,但不会自动关闭我的子视图。我真的不确定为什么子视图会自动关闭以及如何防止它。这是我的 ContentView
代码import SwiftUI
struct Person: Hashable {
var name: String = ""
}
struct ContentView: View {
@State private var patients: [Person]
init() {
var temp: [Person] = []
for index in 0 ..< 3 {
temp.append(Person(name: "\(index)"))
}
patients = temp
}
var body: some View {
NavigationView {
VStack(spacing: 40) {
ForEach($patients, id:\.self) { $patient in
NavigationLink("\(patient.name)") {
ChangeNameView(patient: $patient)
}
}
}
}
}
}
struct ChangeNameView: View {
@Binding var patient: Person
var body: some View {
Button {
patient.name = "New Name"
} label: {
Text("Set New Name")
}
}
}
点击名称将按预期调出子视图。然后点击按钮更改名称,但会立即关闭视图。
问题是因为 Person
是 Hashable
(它只使用 name
属性)并且对于你的 ForEach
,你'重新使用 \.self
作为 id
.
SwiftUI 的 ForEach
使用 id:
参数来跟踪列表中的哪个元素。因为您正在使用 \.self
然后 更改 ChangeNameView
中那个元素的 name
,它看起来不再像同一个元素并且 SwiftUI 删除了层次结构中的子视图(因为旧视图不再存在于列表中)。
一个解决方案是使用真正的 Identifiable
元素,其中 id
是唯一的并且在您更改 name
时不会更新:
struct Person: Hashable, Identifiable { //<-- Here
var id = UUID() //<-- Here
var name: String = ""
}
struct ContentView: View {
@State private var patients: [Person]
init() {
var temp: [Person] = []
for index in 0 ..< 3 {
temp.append(Person(name: "\(index)"))
}
patients = temp
}
var body: some View {
NavigationView {
VStack(spacing: 40) {
ForEach($patients) { $patient in //<-- Here -- when the items are Identifiable, it's essentially like saying `id: \.id`
NavigationLink("\(patient.name)") {
ChangeNameView(patient: $patient)
}
}
}
}
}
}