如何在 SwiftUI 中将呈现视图关闭到选项卡视图的根视图?

Ald*_*rto 7 dismiss ios tabview swiftui modal-sheet

我TabView在我的主页上使用。假设我有 4 个选项卡。在第二个选项卡上,我可以使用 转到另一个视图NavigationLink,并使用 转到另外 2 个视图NavigationLink。然后在最新的视图上,有一个用于呈现视图的按钮,我使用它.fullScreenCover(因为我想全屏呈现它)。

在呈现视图中,我X在要关闭的左侧添加了一个标记navigationBarItems。我使用@Environment(\.presentationMode) var presentationMode和presentationMode.wrappedValue.dismiss()来驳回。但它只会将当前视图忽略到前一个视图,而实际上我想将它忽略到我的视图的根目录,即我的TabView.

有没有办法做到这一点?因为我查阅了一些文章,但没有任何相关的内容,特别是在TabView上下文中。

我也有一个问题:

  1. 这是正确的使用方法吗.fullScreenCover?或者是否有另一种可能的解决方案,例如呈现全屏样式的模式(如果有任何原因我也不确定)。

任何建议将不胜感激,提前谢谢。

Asp*_*eri 5

这presentationMode是一级效果值,即关闭当前显示的一个屏幕即可更改它。

因此,要关闭许多呈现的屏幕,您必须以编程方式实现此操作,如下面的演示所示。

可能的方法是使用自定义EnvironmentKey将其向下传递视图层次结构,而不需要每个级别视图的紧密耦合(如绑定),并且仅在需要时在该级别注入/调用。

使用 Xcode 12.4 / iOS 14.4 测试演示

演示

struct ContentView: View {
    var body: some View {
        TabView {
            Text("Tab1")
                .tabItem { Image(systemName: "1.square") }
            Tab2RootView()
                .tabItem { Image(systemName: "2.square") }
        }
    }
}

struct Tab2RootView: View {
    @State var toRoot = false
    var body: some View {
        NavigationView {
            Tab2NoteView(level: 0)
                .id(toRoot)          // << reset to root !!
        }
        .environment(\.rewind, $toRoot)        // << inject here !!
    }
}

struct Tab2NoteView: View {
    @Environment(\.rewind) var rewind
    let level: Int

    @State private var showFullScreen = false
    var body: some View {
        VStack {
            Text(level == 0 ? "ROOT" : "Level \(level)")
            NavigationLink("Go Next", destination: Tab2NoteView(level: level + 1))
            Divider()
            Button("Full Screen") { showFullScreen.toggle() }
                .fullScreenCover(isPresented: $showFullScreen,
                                        onDismiss: { rewind.wrappedValue.toggle() }) {
                    Tab2FullScreenView()
                }
        }
    }
}

struct RewindKey: EnvironmentKey {
    static let defaultValue: Binding<Bool> = .constant(false)
}

extension EnvironmentValues {
    var rewind: Binding<Bool> {
        get { self[RewindKey.self] }
        set { self[RewindKey.self] = newValue }
    }
}

struct Tab2FullScreenView: View {
    @Environment(\.presentationMode) var mode

    var body: some View {
        Button("Close") { mode.wrappedValue.dismiss() }
    }
}
Run Code Online (Sandbox Code Playgroud)