ios - 从 NavigationView 中关闭 SwiftUI 中的父模式
问题描述
我知道如何从子视图中关闭模式,@Environment (\.presentationMode) var presentationMode / self.presentationMode.wrappedValue.dismiss()
但这是一个不同的问题。
当您在模态窗口中呈现多页NavigationView
并浏览了几个页面时,对 NavigationView 的引用presentationMode
将更改为 NavigationView,因此使用self.presentationMode.wrappedValue.dismiss()
简单地弹出最后一个 NavigationView 而不是关闭包含的模态。
是否有可能 - 如果可以的话 - 从 NavigationView 树的页面中消除包含模式?
这是一个显示问题的简单示例。如果您使用 SwiftUI 创建 Xcode Single View 应用程序项目并用它替换默认ContentView
代码,它应该无需进一步更改即可工作。
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
用于这个用例是不正确的..无论如何)。
建议的方法是通用的,并且适用于模态视图层次结构中的任何视图。经过测试并适用于 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")
}
}
}
推荐阅读
- android - 签名 APK 上的 Firebase com.firebase.client.core.Context.a 错误
- mongodb - 如何在考虑并发的情况下更新多行?
- git - 无法克隆用于编码的存储库?
- reactjs - cleanup() 在使用 Firebase Firestore onSnapshot 的 useEffect() 中不起作用
- java - 广播接收器 Android FireBase
- excel - 根据数据范围删除行
- ssl - 将 .pem 和 .key 转换为 .jks 用于 Jenkins HTTPS
- google-cloud-platform - 图像未在 google automl 云视觉中加载
- macos - macOS 钥匙串中的安全笔记是否已加密?
- django-rest-framework - djnago rest api 数据未在 Angular localhost 页面(客户端)中加载