如何使用 SwiftUI 关闭多个视图

Tak*_*One 5 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()
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码从FirstView过渡到SecondView,从SecondView过渡到ThirdView。并且SecondView 和ThirdView 中的“后退”按钮正常返回上一屏幕。

但是,如果您点击 ThirdView 中的“返回 FirstView”按钮,则将显示 SecondView,而不会返回 FirstView。而在这个操作之后,当你点击SecondView的“返回”按钮时,它不会返回到FirstView。

如何直接从 ThirdView 返回到 FirstView?


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
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案2:基于Asperi的plan 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
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

解决方案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))
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 2

现在根本没有办法(IMO 永远不会 - 这是两个模态会话)...我发现了两种可能值得考虑的可能方法:

A. 从​​一处顺序关闭

Button("back to FirstView") {
    DispatchQueue.main.async {
        self.showThird = false
        DispatchQueue.main.async {
            self.showSecond = false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

B.从不同地方顺序关闭

.sheet(isPresented: self.$showThird, onDismiss: {
    self.showSecond = false // with some additional condition for forced back
})...

...

Button("back to FirstView") {
    self.showThird = false
}
Run Code Online (Sandbox Code Playgroud)