以下是我面临的问题的人为例子。
情况:
我有一个类PersonStore,将类Person存储在一个数组中并已发布。
类Person为每个Person创建一个LegalAge模型,并且该模型已发布
问题:
当对LegalAge中的人员年龄进行更新时,PersonStore的视图不会更新。
我猜测没有更改的原因是因为更改发生在数组内的对象而不是数组本身。我该如何克服?
import SwiftUI
enum LegalAge: Int, CaseIterable {
case UK = 18
case USA = 21
var name: String { "\(self)" }
}
struct ContentView: View {
var body: some View {
MainView()
}
}
/// Displays a list of people and their ages
struct MainView: View {
@ObservedObject var personStore = PersonStore()
@State private var addPerson = false
var body: some View {
NavigationView {
List {
ForEach(personStore.store) { person in
NavigationLink(destination: ShowAge(person: person)) {
HStack {
Text("\(person.name)")
Text("\(person.model.personsAge)")
Text("\(person.model.country)")
Image(systemName: (person.model.personsAge >= person.model.drinkingAge) ? "checkmark.shield.fill" : "xmark.shield.fill").foregroundColor((person.model.personsAge >= person.model.drinkingAge) ? Color.green : Color.red)
}
}
}
}
.navigationBarTitle(Text("Can I Drink?"))
.navigationBarItems(leading: Button(action: { addPerson = true }) { Image(systemName: "plus") }
)
}
/// Open a sheet to create a new person.
.sheet(isPresented: $addPerson) { AddPerson().environmentObject(personStore) }
}
}
/// A Person store to hold all the people.
class PersonStore: ObservableObject {
@Published var store = [Person]()
func addPerson(person: Person) {
store.append(person)
}
func getPerson(name: String) -> Person? {
if let nameAtIndex = store.firstIndex(where: {$0.name == name}) {
return store[nameAtIndex]
}
return nil
}
func insertPerson(person: Person) {
store.append(person)
}
}
/// Form to allow adding people.
struct AddPerson: View {
@EnvironmentObject var personStore: PersonStore
@State private var name: String = ""
@State private var age: String = ""
@State private var country: LegalAge = LegalAge.UK
var body: some View {
NavigationView {
Form {
TextField("Name", text: $name)
TextField("Age", text: $age)
Picker(selection: $country, label: Text("Country")) {
ForEach(LegalAge.allCases, id: \.self) { c in
Text("\(c.name)").tag(c)
}
}
Section {
Button(action: { personStore.addPerson(person: Person(name: name, age: Int(age) ?? 18, country: country))}, label: { Text("Add person" )})
}
}
}
}
}
/// View to show peoples details and allow some of these details to be edited.
struct ShowAge: View {
@ObservedObject var person: Person
@State private var showAgeEditor = false
var body: some View {
VStack {
/// Show the current age.
Text("\(self.person.name)")
Text("\(self.person.model.personsAge)")
Text("\(self.person.model.country)")
Image(systemName: "keyboard")
.onTapGesture {
self.showAgeEditor = true
}
/// Present the sheet to update the age.
.sheet(isPresented: $showAgeEditor) {
SheetView(showAgeEditor: self.$showAgeEditor)
.environmentObject(self.person)
.frame(minWidth: 300, minHeight: 400)
}
}
}
}
/// Sheet to allow editing of persons details.
struct SheetView: View {
@EnvironmentObject var person: Person
@Binding var showAgeEditor: Bool
let maxAge = 21
let minAge = 16
var body: some View {
return VStack(alignment: .leading) {
Text("Name: \(person.name)")
Stepper(value: $person.model.personsAge, in: minAge...maxAge, step: 1) {
Text("Age: \(person.model.personsAge)")
}
Text("Country: \(person.model.country)")
}
}
}
/// ViewModel that creates the Person Object to stored.
class Person: ObservableObject, Identifiable {
@Published var model: LegalDrinkingAge
var name: String
var id = UUID()
init(name: String, age:Int, country: LegalAge) {
self.name = name
self.model = Person.createLegalAge(drinkingAge: country.rawValue, country: "\(country)", personsAge: age)
}
private static func createLegalAge(drinkingAge: Int, country: String, personsAge: Int) -> LegalDrinkingAge {
LegalDrinkingAge(drinkingAge: drinkingAge, country: country, personsAge: personsAge)
}
func updateAge(_ age: Int) {
model.personsAge = age
}
}
struct LegalDrinkingAge {
var drinkingAge: Int = 0
var country: String = ""
var personsAge: Int = 0
mutating func setDrinkingAge(age: Int, country: String, personsAge: Int) {
drinkingAge = age
self.country = country
self.personsAge = personsAge
}
}
答案 0 :(得分:1)
单独查看并使其对人可见
class StorePersonRowView: View {
@ObservedObject person: Person
var body: some View {
HStack {
Text("\(person.name)")
Text("\(person.model.personsAge)")
Text("\(person.model.country)")
Image(systemName: (person.model.personsAge >= person.model.drinkingAge) ? "checkmark.shield.fill" : "xmark.shield.fill").foregroundColor((person.model.personsAge >= person.model.drinkingAge) ? Color.green : Color.red)
}
}
}
并在链接中使用它
ForEach(personStore.store) { person in
NavigationLink(destination: ShowAge(person: person)) {
StorePersonRowView(person: person)
}
}