SwiftUI-如何关闭工作表视图,同时关闭该视图

问题描述:

我想实现该功能.就像来自Apple的查找"视图一样.

I want to achieve the function. Like, "Look up" view that is from Apple.

我的目的是当图纸视图通过导航推入另一个视图时,用户可以点击导航项目按钮以关闭图纸视图.像这样,在gif下面.

My aim is when the sheet view push another view by navigation, the user can tap the navigation item button to close the sheet view. Like, this below gif.

我尝试实现此功能.

我发现了一个问题,那就是用户点击完成"按钮.该应用程序不会关闭工作表视图.它仅将视图弹出到父视图.像这样,在gif下面.

I found a problem that is when the user tap the "Done" button. The App doesn't close the sheet view. It only pop the view to parent view. Like, this below gif.

这是我的代码.

import SwiftUI

struct ContentView: View {
    @State var isShowSheet = false
    var body: some View {
        Button(action: {
            self.isShowSheet.toggle()
        }) {
            Text("Tap to show the sheet")
        }.sheet(isPresented: $isShowSheet) {
            NavView()
        }
    }
}

struct NavView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: NavSubView()) {
                Text("Enter Sub View")
            }
        } .navigationViewStyle(StackNavigationViewStyle())
    }
}

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

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }){
                Text("Done")
            }
        )
    }
}

我如何实现此功能?:)请帮帮我,谢谢.:)

How did I achieve this function? :) Please help me, thank you. :)

由于工作表中的导航可能足够长,并且关闭可能无法在所有导航子视图中进行,因此我更喜欢使用环境来仅在需要时指定关闭功能放置,而不是通过所有导航堆栈传递绑定.

As navigation in sheet might be long enough and closing can be not in all navigation subviews, I prefer to use environment to have ability to specify closing feature only in needed places instead of passing binding via all navigation stack.

这是可行的方法(已通过Xcode 11.2/iOS 13.2测试)

Here is possible approach (tested with Xcode 11.2 / iOS 13.2)

1)定义环境键以存储图纸状态

1) Define environment key to store sheet state

struct ShowingSheetKey: EnvironmentKey {
    static let defaultValue: Binding<Bool>? = nil
}

extension EnvironmentValues {
    var showingSheet: Binding<Bool>? {
        get { self[ShowingSheetKey.self] }
        set { self[ShowingSheetKey.self] = newValue }
    }
}

2)将此环境值设置为工作表内容的根,因此在声明时它将在任何子视图中可用

2) Set this environment value to root of sheet content, so it will be available in any subview when declared

    }.sheet(isPresented: $isShowSheet) {
        NavView()
           .environment(\.showingSheet, self.$isShowSheet)
    }

3)声明&仅在将要使用的子视图中使用环境值

3) Declare & use environment value only in subview where it is going to be used

struct NavSubView: View {
    @Environment(\.showingSheet) var showingSheet

    var body: some View {
        Text("Hello")
        .navigationBarItems(trailing:
            Button("Done") {
                self.showingSheet?.wrappedValue = false
            }
        )
    }
}