Вид не обновляется при нажатии с помощью навигационной ссылки - PullRequest
0 голосов
/ 15 апреля 2020

Я столкнулся с проблемой, когда представление не обновляется автоматически с помощью объекта @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 вместо добавления нового человека по нажатию кнопки. Короче говоря, в массиве людей, скажем, уже есть три человека, и я должен добавить четвертого, только когда приземляюсь на это представление.

Странно то, что человек добавляется, если это представление, если представление root, однако, не работает, когда это представление выдвигается с использованием навигационной ссылки. Во втором случае новый человек добавляется и удаляется сразу, сохраняя количество людей в массиве до трех.

Однако новый человек легко добавляется нажатием кнопки. Я застрял здесь на несколько часов. Любая помощь будет более чем признательна! Заранее спасибо!

РЕДАКТИРОВАТЬ

Я немного отладил, чтобы выяснить проблему. Таким образом, новый человек добавляется в приведенный ниже сценарий ios автоматически в onAppear:

1) Если ContentView является представлением root приложения. 2) Если ContentView выталкивается из самого первого представления в иерархии родительского представления. Имеется в виду, если есть подвиды ContentView. Ссылка навигации из подпредставлений создает эту проблему, однако ссылка навигации непосредственно из ContentView успешно добавляет человека.

А для создания ссылки навигации я использовал:

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

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

соответствует ли это сценарию, который вы упомянули в комментарии:

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)
}
}
0 голосов
/ 16 апреля 2020

хорошо, если я правильно понимаю, вы хотите добавить нового человека в onAppear вместо добавления нового человека одним нажатием кнопки. Но человек добавляется, если это представление является представлением root, однако оно не работает, когда это представление перемещается с использованием навигационной ссылки.

Поэтому я подготовил тест, который работает:

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))
...