ObservedObject не работает в пункте назначения NavigationLink, если есть обновления в родительском

У меня есть два экрана, мастер и деталь, деталь имеет ObservedObject, у которого есть его состояние. Я также хочу скрыть панель навигации на мастере и показать ее на деталях. Для этого у меня есть скрытый статус панели навигации как свойство @State в главном представлении, и я отправляю его обратно в подробное представление как переменную привязки.

Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я обновляю эту переменную на подробном экране, ObservedObject перестает работать.

Вот пример кода, который воспроизводит проблему:

struct ContentView: View {
    @State var navigationBarHidden = true

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden)) {
                    Text("Go Forward")
                }
            }
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(navigationBarHidden)
            .onAppear { self.navigationBarHidden = true }
        }
    }
}

class DetailViewModel: ObservableObject {
    @Published var text = "Didn't work"
}

struct DetailView: View {
    @Binding var navigationBarHidden: Bool
    @ObservedObject var viewModel = DetailViewModel()

    var body: some View {
        VStack {
            Text(viewModel.text)
        }.onAppear {
            self.navigationBarHidden = false
            self.viewModel.text = "Worked"
        }
    }
}

Если я оставлю все как есть, текст не изменится на "Работает". Если я уберу линиюself.navigationBarHidden = false, ObservedObject будет работать правильно, а текст обновится.

Как добиться ожидаемого поведения, обновить панель навигации, сохранив работающий наблюдаемый объект?

1 ответ

Решение

Причина в том, что

NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden)) {
    Text("Go Forward")
}

создать новый DetailView и так далее новый DetailViewModel при активации

пытаться

import SwiftUI

struct ContentView: View {
    @State var navigationBarHidden = true
    @ObservedObject var viewModel = DetailViewModel()
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: DetailView(navigationBarHidden: $navigationBarHidden).environmentObject(viewModel)) {
                    Text("Go Forward")
                }
            }
            .navigationBarTitle("", displayMode: .inline)
            .navigationBarHidden(navigationBarHidden)
            .onAppear { self.navigationBarHidden = true }
        }
    }
}

class DetailViewModel: ObservableObject {
    @Published var text = "Didn't work"
}

struct DetailView: View {
    @Binding var navigationBarHidden: Bool
    @EnvironmentObject var viewModel: DetailViewModel

    var body: some View {
        VStack {
            Text(viewModel.text)
        }.onAppear {
            self.navigationBarHidden = false
            self.viewModel.text = "Worked"
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Теперь вы делитесь моделью с DetailView, и она работает, как ожидалось (написано)

Если я удалю строку self.navigationBarHidden = false, ObservedObject будет работать правильно, и текст обновится.

Если вы удалите эту строку, DetailView не воссоздается (в представлении ничего не изменилось). Состояние не является частью состояния просмотра, это ссылочный тип, поэтому SwiftUI не видит никаких изменений до тех пор, пока не изменятся некоторые значения, которые ими заключены.

Другие вопросы по тегам