SwiftUI 2.0:关闭按钮没有关闭视图 - 如何将关闭按钮设置为 return 到上一个视图?

SwiftUI 2.0: Close button is not dismissing the view - how do I get the Close button to return to the previous view?

在这个频道和网上进行研究时,我尝试使用各种示例中的按钮和导航链接。 NavigationLink 没问题,只是 NavigationView 将我视图中的所有内容都向下推。

我有一个包含图像和文本的视图,如下所示:( x Close) 但是当我使用下面的代码时,“关闭”按钮没有任何作用。

ContentView() 中,我有一个 (?) 按钮,它将我从 WalkthroughView(),然后转到 PageTabView,然后转到此视图,TabDetailsView:

ContentView():

ZStack {
        NavigationView {
            VStack {
                Text("Hello World")
                    .padding()
                    .font(.title)
                    .background(Color.red)
                    .foregroundColor(.white)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button {
                        withAnimation {
                            showOnBoarding = true
                        }
                    } label: {
                        Image(systemName: "questionmark.circle.fill")
                    }
                }
            }
        }
        .accentColor(.red)
        .disabled(showOnBoarding)
        .blur(radius: showOnBoarding ? 3.0 : 0)
        
        if showOnBoarding {
            WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
        }
    }
    .onAppear {
        if !isWalkthroughViewShowing {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
                withAnimation {
                    showOnBoarding.toggle()
                    isWalkthroughViewShowing = true
                }
            }
        }
    }

WalkthroughView():

var body: some View {
    ZStack {
        GradientView()
        VStack {
            PageTabView(selection: $selection)

            // shows Previous/Next buttons only
            ButtonsView(selection: $selection) 
        }
    }
    .transition(.move(edge: .bottom))
}

PageTabView():

var body: some View {
    TabView(selection: $selection) {
        ForEach(tabs.indices, id: \.self) { index in
            TabDetailsView(index: index)
        }
    }
    .tabViewStyle(PageTabViewStyle())
}

下面是 TabDetailsView():

在视图的顶部是这个关闭按钮,按下时应该会返回到 ContentView,但什么也没有发生。

struct TabDetailsView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    let index: Int

然后,体内:

VStack(alignment: .leading) {
        Spacer()
        VStack(alignment: .leading) {
            // Button to close each walkthrough page...
            Button(action: {
                self.presentationMode.wrappedValue.dismiss()
            }) {
                Image(systemName: "xmark.circle.fill")
                Text("Close")
            }
            .padding(.leading)
            .font(.title2)
            .accentColor(.orange)

            Spacer()
            VStack {
                Spacer()
                Image(tabs[index].image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 415)
                    .padding(.leading, 10)
                
                Text(tabs[index].title)
                    .font(.title)
                    .bold()
                
                Text(tabs[index].text)
                    .padding()
                Spacer()
            }
            .foregroundColor(.white)
        }
    }
    if showOnBoarding {
        WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
    }

像上面那样插入视图并不是标准意义上的演示,这就是提供的代码不起作用的原因。

因为这个视图是通过 showOnBoarding 显示的,所以它也应该通过 showOnBoarding 隐藏,因此解决方案是将绑定到这个状态的视图传递到视图中,它将被切换回来。

由于层次结构较深,最合适的方法是使用自定义环境值。为简单起见,我们使用 中的 ResetDefault(您可以在代码中重命名)

因此需要修改:

    if showOnBoarding {
        WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
          .environment(\.resetDefault, $showOnBoarding)
    }

并且在子视图中

struct TabDetailsView: View {
    @Environment(\.resetDefault) var showOnBoarding

    // .. other code

            Button(action: {
                self.showOnBoarding.wrappedValue.toggle() 
            }) {
                Image(systemName: "xmark.circle.fill")
                Text("Close")
            }