问题描述
我使用 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: { $0.id == person.id })!
personModel.persons[personIndex].name = "Updated Name"
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
我用于 List 的解决方法:
示例代码:
//1
private func binding(for person: Person) -> Binding<Person> {
let personIndex = personModel.persons.firstIndex(where: { $0.id == person.id }) ?? 0
return $personModel.persons[personIndex]
}
//2
NavigationLink(destination: PersonDetailView(person: binding(for: person)))
//3
@Binding var person: Person //DetailView
解决方法
此问题似乎已在 Xcode 13 Beta 中修复。
,在我看来,虽然您的解决方法肯定有效,但您首先想知道发生了什么以及为什么需要解决方法。
当您更新 @Published var persons: [Person]
数组的值时,您的详细信息视图会按照您的预期重新呈现。但是您告诉您的视图打印未更改的 name
结构的 var person: Person
值。它仍然与最初创建视图时相同。
如果更换
Text(person.name)
与
Text(personModel.persons.first(where: { $0.id == person.id } )!.name)
它会按照您的预期更新,因为您正在为 Text 视图提供从您刚刚更新的实际 name
中提取的新版本 person
的 PersonModel
值。
所以 List
的参与似乎不是问题,这就是为什么我没有直接回答您的问题“List
我错过了什么?”。希望它无论如何都会有所帮助!
编辑
您可以发送手动更改,但您需要为模型使用类而不是结构。 像这样
Button(action: {
if let personIndex = personModel.persons.firstIndex(where: { $0.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: { $0.id == person.id }) { //<==Here
personModel.persons[personIndex].name = "Updated Name"
personModel.persons[personIndex] = personModel.persons[personIndex]
}
}) {
Text("Update")
}
}
.navigationTitle("Person Detail")
}
}
并使用类
class Person: Identifiable {
var id: UUID
var name: String
init(id: UUID,name: String) {
self.id = id
self.name = name
}
}