如何在SwiftUI中从TabView的子视图导航回到TabView?

问题描述 投票:1回答:1

在SwiftUI中,TabView必须是根视图。因此,您不能使用NavigationLink导航到TabView。假设我的应用程序中有四个屏幕。

屏幕A是包含屏幕B和屏幕C的TabView。屏幕B是具有NavigationLink的列表,可带您进入列表项的详细信息(屏幕D)屏幕C是一个信息视图(在问题中并不重要)屏幕D是列表项详细信息屏幕,您必须首先导航到屏幕b才能到达此处。屏幕D,但是,有一个按钮,应该带您进入屏幕A。

屏幕D如何导航到根屏幕(屏幕A)的两个级别?

ios swift swiftui
1个回答
1
投票

我做了这样的把戏,为我工作。

在SceneDelegate.swift中,我修改了自动生成的代码。


let contentView = ContentView()

if let windowScene = scene as? UIWindowScene {
   let window = UIWindow(windowScene: windowScene)
   // Trick here.
   let nav = UINavigationController(
       rootViewController: UIHostingController(rootView: contentView)
    )
    // I embedded this host controller inside UINavigationController
    //  window.rootViewController = UIHostingController(rootView: contentView)
    window.rootViewController = nav
    self.window = window
    window.makeKeyAndVisible()
}

:我希望将TabView嵌入NavigationView内可以完成相同的工作,但是没有用,这是执行此技巧的原因。

我假设,contentView是要弹出到的视图(一个包含TabView)

然后在从该视图导航的任何视图中,都可以调用

extension View {
    func popToRoot() {
        guard let rootNav = UIApplication.shared.windows.first?.rootViewController as? UINavigationController else { return }
        rootNav.popToRootViewController(animated: true)
    }
}

// Assume you eventually came to this view.
struct DummyDetailView: View {

    var body: some View {

        Text("DetailView")
           .navigationBarItems(trailing:
               Button("Pop to root view") {
                   self.popToRoot()
               }
           )
    }
}

0
投票

“弹出”到根视图的一种有效方法是利用用于导航的isDetailLink上的NavigationLink修饰符。

默认情况下,isDetailLinktrue。该修饰符用于各种视图容器,例如在iPad上,详细视图将显示在右侧。

isDetailLink设置为false意味着该视图将被推入NavigationView堆栈的顶部,也可以将其推下。

[在isDetailLink上将NavigationLink设置为false的同时,将isActive绑定传递到每个子目标视图。当要弹出到根视图时,将值设置为false,它将弹出所有内容:

import SwiftUI

struct ScreenA: View {
    @State var isActive : Bool = false

    var body: some View {
        NavigationView {
            NavigationLink(
                destination: ScreenB(rootIsActive: self.$isActive),
                isActive: self.$isActive
            ) {
                Text("ScreenA")
            }
            .isDetailLink(false)
            .navigationBarTitle("Screen A")
        }
    }
}

struct ScreenB: View {
    @Binding var rootIsActive : Bool

    var body: some View {
        NavigationLink(destination: ScreenD(shouldPopToRootView: self.$rootIsActive)) {
            Text("Next screen")
        }
        .isDetailLink(false)
        .navigationBarTitle("Screen B")
    }
}

struct ScreenD: View {
    @Binding var shouldPopToRootView : Bool

    var body: some View {
        VStack {
            Text("Last Screen")
            Button (action: { self.shouldPopToRootView = false } ){
                Text("Pop to root")
            }
        }.navigationBarTitle("Screen D")
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.