【问题标题】:SwiftUI Dismiss Multiple Modal SheetsSwiftUI 关闭多个模式表
【发布时间】:2020-02-06 09:31:55
【问题描述】:

我在根视图中使用.sheet(isPresented: self.$showModal) 来呈现模式。在模式中,我使用NavigationView 引导用户浏览各个页面(用于用户配置文件构建器)。

在我的导航堆栈的最后一页中,我使用@Environment(\.presentationMode) var presentationMode 和一个调用self.presentationMode.wrappedValue.dismiss() 的按钮来关闭模式。但是,这只会关闭导航堆栈中的最后一页,而我只是在前一页结束。我想要做的是关闭整个导航堆栈并最终回到根视图。

向下滑动以关闭模式会产生所需的结果,但我想通过按钮以编程方式执行此操作。

目前这在 SwiftUI 中是否可行,或者这是在模态表中使用 NavigationView 时出现的问题?

【问题讨论】:

标签: ios swift swiftui


【解决方案1】:

解决方案 1 - 自定义 EnvironmentKey

一种可能的解决方案是使用注入到每个环境的自定义EnvironmentKey

struct PresentationKey: EnvironmentKey {
    static let defaultValue: [Binding<Bool>] = []
}

extension EnvironmentValues {
    var presentations: [Binding<Bool>] {
        get { return self[PresentationKey] }
        set { self[PresentationKey] = newValue }
    }
}

演示:

struct ContentView: View {
    @Environment(\.presentations) private var presentations
    @State private var showSheet = false

    var body: some View {
        Button("Show sheet") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            SheetView()
                .environment(\.presentations, presentations + [$showSheet])
        }
    }
}
struct SheetView: View {
    @Environment(\.presentations) private var presentations
    @State private var showSheet = false

    var body: some View {
        Button("Show another sheet") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            SheetNavigationView()
                .environment(\.presentations, presentations + [$showSheet])
        }
    }
}
struct SheetNavigationView: View {
    var body: some View {
        NavigationView {
            NavigationLink("Link", destination: SheetNavigationDetailView())
        }
    }
}
struct SheetNavigationDetailView: View {
    @Environment(\.presentations) private var presentations

    var body: some View {
        Button("Pop to root") {
            presentations.forEach {
                $0.wrappedValue = false
            }
        }
    }
}

解决方案 2 - 关闭 UIKit rootViewController

struct SheetNavigationDetailView: View {

    var body: some View {
        Button("Pop to root") {
            UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true)
        }
    }
}

【讨论】:

  • 谢谢!第二个解决方案完美!
【解决方案2】:

您可以将 showModal 作为绑定传递到以下屏幕,而不是使用 PresentationValue 将 showModal 设置为 false。

【讨论】:

  • 谢谢,这对我有用。我最终在我的 NavigationStack 的每个页面中创建了一个 @Binding var showModal,然后将绑定传递到每个连续的页面,直到我到达我真正想要切换它的末尾。不确定这是否是最有效的方法,但它确实有效。
  • 你有机会分享这个的完整样本吗?我正在为同样的方法而苦苦挣扎。将showModal 作为绑定传递,但我的导航堆栈中的每个项目都只是添加到最后一个项目的下方,而不是实际替换它。
【解决方案3】:
@State private var modalOpen: Bool = false

.sheet(isPresented: self.$modalOpen, onDismiss: {
            // code that triggers when modal is closed
        }) {
        Button(action: {
            self.modalOpen.toggle()
        }) {
           Text("Schließen")
        }

【讨论】:

    【解决方案4】:

    在 SwiftUI 中。

    使用SheetKit 关闭所有带有动画控件的工作表。

    SheetKit().dismissAllSheets(animation:false)
    

    或使用NavigationViewKit 在导航视图中弹回根视图

    【讨论】:

      猜你喜欢
      • 2019-10-24
      • 2021-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      相关资源
      最近更新 更多