ObservedObject не работает по назначению NavigationLink, если есть обновления на родительском - PullRequest
0 голосов
/ 06 марта 2020

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

Проблема, с которой я столкнулся, заключается в том, что всякий раз, когда я обновляю эту переменную на подробном экране, 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 Ответ

1 голос
/ 06 марта 2020

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

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

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

try

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 будет работать правильно, а текст обновится.

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

...