更新模型时不会更新详细视图(使用列表)SwiftUI
Detail View is not updated when the model is updated (Using List) SwiftUI
我正在使用 List 在主视图中显示模型。当我在详细视图中更新模型时,它不会在详细视图中更新。
当我不使用 List
时,详细视图会更新。 List
我错过了什么?
struct Person: Identifiable {
var id: UUID
var name: String
}
class PersonModel: ObservableObject {
@Published var persons: [Person] = [Person(id: UUID(), name: "Ege")]
}
struct PersonListView: View {
@StateObject private var personModel = PersonModel()
var body: some View {
NavigationView {
List {
ForEach(personModel.persons) { person in
NavigationLink(destination: PersonDetailView(person: person).environmentObject(personModel)) {
Text(person.name)
}
}
}
.navigationTitle("Persons")
}
}
}
struct PersonDetailView: View {
let person: Person
@EnvironmentObject var personModel: PersonModel
var body: some View {
VStack {
Text(person.name)
Button(action: {
let personIndex = personModel.persons.firstIndex(where: { [=10=].id == person.id })!
personModel.persons[personIndex].name = "Updated Name"
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
我用于 List 的解决方法:
- 为 NavigationLink 使用自定义绑定功能。
示例代码:
//1
private func binding(for person: Person) -> Binding<Person> {
let personIndex = personModel.persons.firstIndex(where: { [=11=].id == person.id }) ?? 0
return $personModel.persons[personIndex]
}
//2
NavigationLink(destination: PersonDetailView(person: binding(for: person)))
//3
@Binding var person: Person //DetailView
- 在详细视图中使用另一个
@State
,该视图已通过 passed 初始化
onAppear 方法中的模型。
编辑
您可以发送手动更改,但您需要使用 class 而不是模型的结构。
像这样
Button(action: {
if let personIndex = personModel.persons.firstIndex(where: { [=10=].id == person.id }) { //<==Here
personModel.persons[personIndex].name = "Updated Name"
personModel.objectWillChange.send() //<==Here
}
})
可能的解决方案是更新数据并将元素重新分配给数组。
struct PersonDetailView: View {
let person: Person
@EnvironmentObject var personModel: PersonModel
var body: some View {
VStack {
Text(person.name)
Button(action: {
if let personIndex = personModel.persons.firstIndex(where: { [=11=].id == person.id }) { //<==Here
personModel.persons[personIndex].name = "Updated Name"
personModel.persons[personIndex] = personModel.persons[personIndex]
}
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
并使用class
class Person: Identifiable {
var id: UUID
var name: String
init(id: UUID, name: String) {
self.id = id
self.name = name
}
}
在我看来,尽管您的变通办法确实有效,但您想首先了解发生了什么以及为什么需要变通办法。
当您更新 @Published var persons: [Person]
数组的值时,您的详细视图将按照您的预期重新呈现。但是您告诉您的视图打印 var person: Person
结构的 name
值,该值没有改变。还是和刚创建视图时一样。
如果你更换
Text(person.name)
和
Text(personModel.persons.first(where: { [=11=].id == person.id } )!.name)
它会按照您的预期进行更新,因为您正在为文本视图提供新版本 person
的 name
值,该值是从您刚刚创建的实际 PersonModel
中提取的已更新。
所以 List
的参与似乎不是问题,这就是为什么我没有直接回答你的问题“List
我错过了什么?”。希望它能有所帮助!
此问题似乎已在 Xcode 13 Beta 中修复。
我正在使用 List 在主视图中显示模型。当我在详细视图中更新模型时,它不会在详细视图中更新。
当我不使用 List
时,详细视图会更新。 List
我错过了什么?
struct Person: Identifiable {
var id: UUID
var name: String
}
class PersonModel: ObservableObject {
@Published var persons: [Person] = [Person(id: UUID(), name: "Ege")]
}
struct PersonListView: View {
@StateObject private var personModel = PersonModel()
var body: some View {
NavigationView {
List {
ForEach(personModel.persons) { person in
NavigationLink(destination: PersonDetailView(person: person).environmentObject(personModel)) {
Text(person.name)
}
}
}
.navigationTitle("Persons")
}
}
}
struct PersonDetailView: View {
let person: Person
@EnvironmentObject var personModel: PersonModel
var body: some View {
VStack {
Text(person.name)
Button(action: {
let personIndex = personModel.persons.firstIndex(where: { [=10=].id == person.id })!
personModel.persons[personIndex].name = "Updated Name"
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
我用于 List 的解决方法:
- 为 NavigationLink 使用自定义绑定功能。
示例代码:
//1
private func binding(for person: Person) -> Binding<Person> {
let personIndex = personModel.persons.firstIndex(where: { [=11=].id == person.id }) ?? 0
return $personModel.persons[personIndex]
}
//2
NavigationLink(destination: PersonDetailView(person: binding(for: person)))
//3
@Binding var person: Person //DetailView
- 在详细视图中使用另一个
@State
,该视图已通过 passed 初始化 onAppear 方法中的模型。
编辑
您可以发送手动更改,但您需要使用 class 而不是模型的结构。 像这样
Button(action: {
if let personIndex = personModel.persons.firstIndex(where: { [=10=].id == person.id }) { //<==Here
personModel.persons[personIndex].name = "Updated Name"
personModel.objectWillChange.send() //<==Here
}
})
可能的解决方案是更新数据并将元素重新分配给数组。
struct PersonDetailView: View {
let person: Person
@EnvironmentObject var personModel: PersonModel
var body: some View {
VStack {
Text(person.name)
Button(action: {
if let personIndex = personModel.persons.firstIndex(where: { [=11=].id == person.id }) { //<==Here
personModel.persons[personIndex].name = "Updated Name"
personModel.persons[personIndex] = personModel.persons[personIndex]
}
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
并使用class
class Person: Identifiable {
var id: UUID
var name: String
init(id: UUID, name: String) {
self.id = id
self.name = name
}
}
在我看来,尽管您的变通办法确实有效,但您想首先了解发生了什么以及为什么需要变通办法。
当您更新 @Published var persons: [Person]
数组的值时,您的详细视图将按照您的预期重新呈现。但是您告诉您的视图打印 var person: Person
结构的 name
值,该值没有改变。还是和刚创建视图时一样。
如果你更换
Text(person.name)
和
Text(personModel.persons.first(where: { [=11=].id == person.id } )!.name)
它会按照您的预期进行更新,因为您正在为文本视图提供新版本 person
的 name
值,该值是从您刚刚创建的实际 PersonModel
中提取的已更新。
所以 List
的参与似乎不是问题,这就是为什么我没有直接回答你的问题“List
我错过了什么?”。希望它能有所帮助!
此问题似乎已在 Xcode 13 Beta 中修复。