使用导航推送时视图不更新 Link

View does not update when pushed using Navigation Link

我遇到了一个问题,即视图不会使用 @Observable 对象自动更新。

struct Person: Identifiable {
  var id: Int
  var name: String

  init(id: Int, name: String){
      self.id = id
      self.name = name
  }

}

class People: ObservableObject {
  @Published var people: [Person]
  @Published var kitchens: [Kitchen]

  init(){
      self.people = [
          Person(id: 1, name:"Javier"),
          Person(id: 2, name:"Juan"),
          Person(id: 3, name:"Pedro")]
 }
}

struct ContentView: View {
@ObservedObject var mypeople: People

var body: some View {
    VStack{
        ForEach(mypeople.people){ person in
            Text("\(person.name)")
        }
        Button(action: {
            self.mypeople.people.append(Person(id: 7, name: "New person"))
        }) {
            Text("Add/Change name")
        }
    }.onAppear {
        self.mypeople.people.append(Person(id: 7, name: "New person"))
    }
}
}

所以,我想做的是我必须在 onAppear 中添加一个新人,而不是在点击按钮时添加一个新人。简而言之,people 数组可以说已经有三个人,我必须在登陆该视图时添加第四个人。

奇怪的是,如果此视图是根视图,则会添加人员,但是,当使用导航 Link 推送此视图时,它不起作用。在第二种情况下,立即添加和删除一个新人,使 people 数组计数为三。

但是,轻按按钮即可轻松添加新人。我被困在这里几个小时。任何帮助将不胜感激!提前致谢!

编辑

我调试了一点以找出问题所在。因此,在以下情况下,新人会在 onAppear 中自动添加:

1) 如果ContentView 是应用程序的根视图。 2) 如果从父视图层次结构中的第一个视图推送 ContentView。意思是,如果有 ContentView 的子视图。来自子视图的导航 Link 会产生此问题,但是,直接来自 ContentView 的导航 link 会成功添加人物。

为了创建导航Link,我使用了:

NavigationLink(destination:  ContentView()) {
     Text("View All")
}

好的,如果我没理解错的话,你想在 onAppear 中添加一个新人,而不是点击按钮添加一个新人。但是,如果此视图是根视图,则会添加此人,但是,当使用导航 Link.

推送此视图时,它不起作用

所以我设计了一个有效的测试:

struct Person: Identifiable {
var id: Int
var name: String
init(id: Int, name: String){
    self.id = id
    self.name = name
}
}

struct Kitchen: Identifiable {
var id: Int
var name: String
init(id: Int, name: String){
    self.id = id
    self.name = name
}
}

class People: ObservableObject {
@Published var people: [Person]
@Published var kitchens: [Kitchen]
init() {
    self.people = [ Person(id: 1, name:"Javier"),Person(id: 2, name:"Juan"),Person(id: 3, name:"Pedro")]
    self.kitchens = [ Kitchen(id: 1, name:"Kitchen1"),Kitchen(id: 2, name:"Kitchen2"), Kitchen(id: 3, name:"Kitchen3")]
}
}

struct SecondView: View {
@ObservedObject var mypeople: People
@State var newId = Int(arc4random())
var body: some View {
    VStack{
        ForEach(mypeople.people){ person in
            Text("\(person.name)")
        }
        Button(action: {
            self.mypeople.people.append(Person(id: self.newId, name: "New person"))
        }) {
            Text("Add/Change name")
        }
    }.onAppear {
        print("--------> onAppear")
        self.mypeople.people.append(Person(id: self.newId, name: "New person"))
    }
}
}

struct ContentView: View {
@ObservedObject var mypeople: People
var body: some View {
    NavigationView {
        NavigationLink(destination: SecondView(mypeople: mypeople)) {
            Text("View All")
        }
    }.navigationViewStyle(StackNavigationViewStyle())
}
}

当然在SceneDelegate中,你要声明:

var people = People()
window.rootViewController = UIHostingController(rootView: ContentView(mypeople: people))

这是否解决了您在评论中提到的场景:

struct TheNavView: View {
@ObservedObject var mypeople: People
@State var newId = Int(arc4random())
var body: some View {
    // the view that create "New person" onAppear
    VStack{
        ForEach(mypeople.people){ person in
            Text("\(person.name)")
        }
        Button(action: {
            self.mypeople.people.append(Person(id: self.newId, name: "New person"))
        }) {
            Text("Add/Change name")
        }
    }.onAppear {
        print("--------> onAppear self.newId: \(self.newId)")
        self.mypeople.people.append(Person(id: self.newId, name: "New person"))
    }
}
}

struct TheSubView: View {
@ObservedObject var mypeople: People
var body: some View {
    // the subView that pushes using NavigationLink
    NavigationView {
        NavigationLink(destination: TheNavView(mypeople: mypeople)) {
            Text("View All")
        }
    }.navigationViewStyle(StackNavigationViewStyle())
}
}

struct ContentView: View {
@ObservedObject var mypeople: People
var body: some View {
    // the ContentView with a subView
    TheSubView(mypeople: mypeople)
}
}