如何使用SwiftUI关闭多个视图 导入快捷界面 结构ContentView:View{ @状态变量showSecond=false @状态变量showThird=false var body:一些观点{ VStack(间距:50){ 文本(“第一视图”) 按钮(“至第二视图”){ self.showSecond=true } .工作表(显示:$showSecond){ VStack(间距:50){ 文本(“第二视图”) 按钮(“至第三视图”){ self.showThird=true } .表(显示:self.$showThird){ VStack(间距:50){ 文本(“第三视图”) 按钮(“后退”){ self.showThird=false } 按钮(“返回第一视图”){ self.showThird=false self.showSecond=false } } } 按钮(“后退”){ self.showSecond=false } } } } } } 结构内容视图\u预览:PreviewProvider{ 静态var预览:一些视图{ ContentView() } }
上面的代码从FirstView转换到SecondView,从SecondView转换到ThirdView。SecondView和ThirdView中的“后退”按钮正常返回上一屏幕 但是,如果您点击第三视图中的“返回第一视图”按钮,将显示第二视图,而不返回第一视图。完成此操作后,当您点击SecondView的“后退”按钮时,它不会返回到FirstView 如何直接从ThirdView返回FirstView如何使用SwiftUI关闭多个视图 导入快捷界面 结构ContentView:View{ @状态变量showSecond=false @状态变量showThird=false var body:一些观点{ VStack(间距:50){ 文本(“第一视图”) 按钮(“至第二视图”){ self.showSecond=true } .工作表(显示:$showSecond){ VStack(间距:50){ 文本(“第二视图”) 按钮(“至第三视图”){ self.showThird=true } .表(显示:self.$showThird){ VStack(间距:50){ 文本(“第三视图”) 按钮(“后退”){ self.showThird=false } 按钮(“返回第一视图”){ self.showThird=false self.showSecond=false } } } 按钮(“后退”){ self.showSecond=false } } } } } } 结构内容视图\u预览:PreviewProvider{ 静态var预览:一些视图{ ContentView() } },swift,swiftui,Swift,Swiftui,上面的代码从FirstView转换到SecondView,从SecondView转换到ThirdView。SecondView和ThirdView中的“后退”按钮正常返回上一屏幕 但是,如果您点击第三视图中的“返回第一视图”按钮,将显示第二视图,而不返回第一视图。完成此操作后,当您点击SecondView的“后退”按钮时,它不会返回到FirstView 如何直接从ThirdView返回FirstView 于2020年2月19日增补 我已经根据答案添加了解决方案代码 解决方案1:基于Asperi
于2020年2月19日增补 我已经根据答案添加了解决方案代码 解决方案1:基于Asperi的A计划
struct ContentView: View {
@State var showSecond = false
@State var showThird = false
var body: some View {
VStack(spacing: 50) {
Text("FirstView")
Button("to SecondView") {
self.showSecond = true
}
.sheet(isPresented: $showSecond) {
VStack(spacing: 50) {
Text("SecondView")
Button("to ThirdView") {
self.showThird = true
}
.sheet(isPresented: self.$showThird) {
VStack(spacing: 50) {
Text("ThirdView")
Button("back") {
self.showThird = false
}
Button("back to FirstView") {
DispatchQueue.main.async {
self.showThird = false
DispatchQueue.main.async {
self.showSecond = false
}
}
}
}
}
Button("back") {
self.showSecond = false
}
}
}
}
}
}
解决方案2:基于Asperi的B计划
struct ContentView: View {
@State var showSecond = false
@State var showThird = false
@State var backToFirst = false
var body: some View {
VStack(spacing: 50) {
Text("FirstView")
Button("to SecondView") {
self.showSecond = true
}
.sheet(isPresented: $showSecond) {
VStack(spacing: 50) {
Text("SecondView")
Button("to ThirdView") {
self.showThird = true
}
.sheet(isPresented: self.$showThird, onDismiss: {
if self.backToFirst {
self.showSecond = false
}
}) {
VStack(spacing: 50) {
Text("ThirdView")
Button("back") {
self.showThird = false
self.backToFirst = false
}
Button("back to FirstView") {
self.showThird = false
self.backToFirst = true
}
}
}
Button("back") {
self.showSecond = false
}
}
}
}
}
}
解决方案3:基于约瑟夫的建议
struct ContentView: View {
@State var showSecond = false
@State var showThird = false
var body: some View {
GeometryReader { geometry in
ZStack {
VStack(spacing: 50) {
Text("FirstView")
Button("to SecondView") {
self.showSecond = true
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Rectangle().foregroundColor(.white))
if self.showSecond {
VStack(spacing: 50) {
Text("SecondView")
Button("to ThirdView") {
self.showThird = true
}
Button("back") {
self.showSecond = false
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Rectangle().foregroundColor(.white))
if self.showThird {
VStack(spacing: 50) {
Text("ThirdView")
Button("back") {
self.showThird = false
}
Button("back to FirstView") {
self.showThird = false
self.showSecond = false
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Rectangle().foregroundColor(.white))
}
}
}
}
}
}
目前还没有办法(国际海事组织也永远不会——这是两次模式会议)。。。我发现了两种可能值得考虑的方法:
A.从一个地方顺序关闭
Button("back to FirstView") {
DispatchQueue.main.async {
self.showThird = false
DispatchQueue.main.async {
self.showSecond = false
}
}
}
B.从不同位置顺序关闭
.sheet(isPresented: self.$showThird, onDismiss: {
self.showSecond = false // with some additional condition for forced back
})...
...
Button("back to FirstView") {
self.showThird = false
}
另一个/咳嗽/“解决方案”-可能是一个稍微不同的场景
-但无论如何:
struct ContentView: View {
var body: some View {
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Show Second View")
.font(.largeTitle)
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct SecondView: View {
@Environment(\.presentationMode) var presentationMode
@State private var showModal = false
var body: some View {
GeometryReader { geometry in
ZStack {
Rectangle()
.foregroundColor(.gray)
.frame(width: geometry.size.width, height: geometry.size.height)
Button(action: {
withAnimation {
self.showModal.toggle()
}
}) {
Text("Show Third View")
.font(.largeTitle)
.foregroundColor(.white)
}
if self.showModal {
VStack {
Button(action: {
self.presentationMode.wrappedValue.dismiss()
} ) {
Text("Show First View")
.font(.largeTitle)
.foregroundColor(.white)
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Rectangle().foregroundColor(.orange))
.transition(.move(edge: .trailing))
}
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
Asperi的解决方案适用于同时关闭两个屏幕,但不适用于更多屏幕。在这种情况下,我们需要在以下两种方法中添加
DispatchQueue.main.asyncAfter(截止日期:.now()+.millides(300))
:
self.showFourth = false
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
self.showThird = false
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
self.showSecond = false
}
}
。毫秒(200)
不够。谢谢您的建议!我试过你的建议了。A计划没有效果。但是,当我使用“DispatchQueue.main.asyncAfter(截止日期:.now()+0.01)”而不是“DispatchQueue.main.async”时,它现在可以按照建议工作。B计划按建议进行。当我使用此计划时,我需要添加一个新的状态变量,该变量可以确定是否返回到位于“.onDismiss”的FirstView。在任何情况下,这两个计划都是返回FirstView的逐步过渡,而不是直接过渡。我想等待其他人的解决方案。我再次检查。planA使用了如图所示的代码。当我之前检查它时,我在设置showThird之前忽略了DispatchQueue。我在问题区域添加了一个基于此建议的代码。Z-堆叠基于@State
布尔值渲染的多个动画视图可能是一种使合成的展开分段“深入”几层的方法。它不太优雅,但是。。。是的,谢谢你的建议!您关于使用zstack覆盖视图的建议非常有用。如果我们不关心使用工作表来设置模态转换的动画,那么这种方法非常有效。