SwiftUI: как переключиться на новый стек навигации с помощью NavigationViews

В настоящее время я использую SwiftUI Beta 5. У меня есть рабочий процесс, который включает навигацию по серии представлений. Последнее представление включает в себя операцию, которая заполняет загрузку данных в приложение и завершает этот конкретный рабочий процесс.

После того, как данные были загружены, пользователь должен иметь возможность начать новый рабочий процесс (ы). Я хотел бы "забыть" о старом NavigationView, поскольку нет смысла возвращаться назад через стек навигации после завершения рабочего процесса. Вместо этого я хотел бы перейти к представлению "запуска", которое фактически становится корнем нового представления навигации.

Как одно представление в стеке навигации можно использовать для перехода к другому представлению с другим NavigationView (и, следовательно, становится корнем для нового стека навигации) с использованием SwiftUI NavigagationViews?

2 ответа

Во-первых, извините, я хотел оставить простой комментарий, но недостаточно репутации:(

Я только что обновил свой способ, чтобы вернуться к руту вы на stackru.com/a/57513566/7786555

Вы на самом деле дали мне идею с вашим комментарием для нового способа вернуться к корню. Имея новый корневой вид. Если вы принудительно обновите представление структуры, управляющее корневым представлением, оно автоматически сделает то, что вы хотите. Здесь только возвращается к корню (без анимации). Вы можете адаптировать пример для изменения корневого представления (вместо использования того же самого) в соответствии с вашими потребностями.

struct DetailViewB: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    @State var fullDissmiss:Bool = false
    var body: some View {
        SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
            VStack {
                Text("This is Detail View B.")

                Button(action: { self.presentationMode.wrappedValue.dismiss() } )
                { Text("Pop to Detail View A.") }

                Button(action: {
                    self.fullDissmiss = true
                } )
                { Text("Pop two levels to Master View with SGGoToRoot.") }
            }
        }
    }
}

struct DetailViewA: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    @State var fullDissmiss:Bool = false
    var body: some View {
        SGNavigationChildsView(fullDissmiss: self.fullDissmiss){
            VStack {
                Text("This is Detail View A.")

                NavigationLink(destination: DetailViewB() )
                { Text("Push to Detail View B.") }

                Button(action: { self.presentationMode.wrappedValue.dismiss() } )
                { Text("Pop one level to Master.") }

                Button(action: { self.fullDissmiss = true } )
                { Text("Pop one level to Master with SGGoToRoot.") }
            }
        }
    }
}

struct MasterView: View {
    var body: some View {
        VStack {
            Text("This is Master View.")
            NavigationLink(destination: DetailViewA() )
            { Text("Push to Detail View A.") }
        }
    }
}

struct ContentView: View {

    var body: some View {
        SGRootNavigationView{
            MasterView()
        }
    }
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

struct SGRootNavigationView<Content>: View where Content: View {
    let cancellable = NotificationCenter.default.publisher(for: Notification.Name("SGGoToRoot"), object: nil)

    let content: () -> Content

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }

    @State var goToRoot:Bool = false

    var body: some View {
        return
            Group{
            if goToRoot == false{
                NavigationView {
                content()
                }
            }else{
                NavigationView {
                content()
                }
            }
            }.onReceive(cancellable, perform: {_ in
                DispatchQueue.main.async {
                    self.goToRoot.toggle()
                }
            })
    }
}

struct SGNavigationChildsView<Content>: View where Content: View {
    let notification = Notification(name: Notification.Name("SGGoToRoot"))

    var fullDissmiss:Bool{
        get{ return false }
        set{ if newValue {self.goToRoot()} }
    }

    let content: () -> Content

    init(fullDissmiss:Bool, @ViewBuilder content: @escaping () -> Content) {
        self.content = content
        self.fullDissmiss = fullDissmiss
    }

    var body: some View {
        return Group{
            content()
        }
    }

    func goToRoot(){
        NotificationCenter.default.post(self.notification)
    }
}

Вот как мы решили этот вопрос: у нас было представление main/root/launch, из которого пользователь мог нажать кнопку, чтобы запустить какой-либо бизнес-процесс. Это откроет лист, который будет отображать модальное всплывающее окно. (Ширина и высота листов могут быть настроены так, чтобы они занимали большую часть/весь экран.)

Лист будет иметь NavigationView. Это позволит пользователю пройти серию представлений как часть рабочего процесса. Флаг «представленный» передается как привязка из основного представления к каждому представлению с навигацией.

Когда пользователь достигает последнего представления и нажимает кнопку «Отправить/Готово/Готово», чтобы завершить этот конкретный рабочий процесс, для «представленной» привязки может быть установлено значение false, что закрывает модальное всплывающее окно и возвращает пользователя обратно в основное представление. .

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