从NavigationView中取消SwiftUI中的父模态 [英] Dismiss a parent modal in SwiftUI from a NavigationView
问题描述
我知道如何使用@Environment (\.presentationMode) var presentationMode / self.presentationMode.wrappedValue.dismiss()
从子视图中删除模态,但这是一个不同的问题.
I am aware of how to dismiss a modal from a child view using @Environment (\.presentationMode) var presentationMode / self.presentationMode.wrappedValue.dismiss()
but this is a different issue.
当您在模式窗口中显示多页NavigationView
并浏览了几页时,对presentationMode
的引用将更改为NavigationView,因此使用self.presentationMode.wrappedValue.dismiss()
只是弹出最后一个NavigationView比消除包含的模态.
When you present a multi-page NavigationView
in a modal window, and have navigated through a couple of pages, the reference to presentationMode
changes to be the NavigationView, so using self.presentationMode.wrappedValue.dismiss()
simply pops the last NavigationView rather than dismissing the containing modal.
是否可以-以及如何-从NavigationView树中的页面中消除包含的模态?
Is it possible - and if so how - to dismiss the containing modal from a page in a NavigationView tree?
这是一个显示问题的简单示例.如果您使用SwiftUI创建一个Xcode Single View应用项目,并用它替换默认的ContentView
代码,则该代码无需任何进一步的更改即可工作.
Here's a simple example showing the problem. If you create an Xcode Single View app project using SwiftUI and replace the default ContentView
code with this, it should work with no further changes.
import SwiftUI
struct ContentView: View {
@State var showModal: Bool = false
var body: some View {
Button(action: {
self.showModal.toggle()
}) {
Text("Launch Modal")
}
.sheet(isPresented: self.$showModal, onDismiss: {
self.showModal = false
}) {
PageOneContent()
}
}
}
struct PageOneContent: View {
var body: some View {
NavigationView {
VStack {
Text("I am Page One")
}
.navigationBarTitle("Page One")
.navigationBarItems(
trailing: NavigationLink(destination: PageTwoContent()) {
Text("Next")
})
}
}
}
struct PageTwoContent: View {
@Environment (\.presentationMode) var presentationMode
var body: some View {
NavigationView {
VStack {
Text("This should dismiss the modal. But it just pops the NavigationView")
.padding()
Button(action: {
// How to dismiss parent modal here instead
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Finish")
}
.padding()
.foregroundColor(.white)
.background(Color.blue)
}
.navigationBarTitle("Page Two")
}
}
}
推荐答案
以下是基于用法自己明确创建的环境密钥的可行方法(实际上,我觉得在此用例中使用presentationMode
是不正确的. . 反正).
Here is possible approach based on usage own explicitly created environment key (actually I have feeling that it is not correct to use presentationMode
for this use-case.. anyway).
提议的方法是通用的,并且可以从模式视图层次结构的任何视图中使用.经过测试与Xcode 11.2/iOS 13.2兼容.
Proposed approach is generic and works from any view in modal view hierarchy. Tested & works with Xcode 11.2 / iOS 13.2.
// define env key to store our modal mode values
struct ModalModeKey: EnvironmentKey {
static let defaultValue = Binding<Bool>.constant(false) // < required
}
// define modalMode value
extension EnvironmentValues {
var modalMode: Binding<Bool> {
get {
return self[ModalModeKey.self]
}
set {
self[ModalModeKey.self] = newValue
}
}
}
struct ParentModalTest: View {
@State var showModal: Bool = false
var body: some View {
Button(action: {
self.showModal.toggle()
}) {
Text("Launch Modal")
}
.sheet(isPresented: self.$showModal, onDismiss: {
}) {
PageOneContent()
.environment(\.modalMode, self.$showModal) // < bind modalMode
}
}
}
struct PageOneContent: View {
var body: some View {
NavigationView {
VStack {
Text("I am Page One")
}
.navigationBarTitle("Page One")
.navigationBarItems(
trailing: NavigationLink(destination: PageTwoContent()) {
Text("Next")
})
}
}
}
struct PageTwoContent: View {
@Environment (\.modalMode) var modalMode // << extract modalMode
var body: some View {
NavigationView {
VStack {
Text("This should dismiss the modal. But it just pops the NavigationView")
.padding()
Button(action: {
self.modalMode.wrappedValue = false // << close modal
}) {
Text("Finish")
}
.padding()
.foregroundColor(.white)
.background(Color.blue)
}
.navigationBarTitle("Page Two")
}
}
}
这篇关于从NavigationView中取消SwiftUI中的父模态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!