如何使用SwiftUI关闭多个视图

时间:2019-12-24 09:06:32

标签: swift swiftui

import SwiftUI

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") {
                                self.showThird = false
                                self.showSecond = false
                            }
                        }
                    }
                    Button("back") {
                        self.showSecond = false
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

以上代码从FirstView过渡到SecondView,并且从SecondView过渡到ThirdView。然后,SecondView和ThirdView中的“返回”按钮通常会返回到上一个屏幕。

但是,如果您在ThirdView中点击“返回FirstView”按钮,将显示SecondView而不会返回FirstView。在执行此操作后,当您点击SecondView的“后退”按钮时,它不会返回到FirstView。

如何直接从ThirdView返回FirstView?

3 个答案:

答案 0 :(得分:1)

目前根本没有办法(而且IMO永远不会-这是两个模式会议)...我发现了两种可能值得考虑的方法:

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
}

答案 1 :(得分:1)

另一个 /咳嗽/ “解决方案”-可能情况略有不同 -但无论如何:

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)
        }
    }
}

答案 2 :(得分:1)

Asperi的解决方案可一次消除两个屏幕,但不适用于更多屏幕。在这种情况下,我们需要在两种方法中都添加DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300))

self.showFourth = false
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
    self.showThird = false
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300)) {
        self.showSecond = false
    }
}

.milliseconds(200)不够。