As the time flies, by App get more and more complicated shape.
In some cases the App flow might be:
View A -> View B -> C -> D and then back D -> C -> B -> A..
but sometimes i need to skip the view and go D -> B -> A..
In some cases its A -> C -> D and then D -> A
I started to use NavigationView/NavigationLink and in some cases i use the following approach:
let weekView = WeekView(journey: journey, isRoot: isRoot).environmentObject(self.thisSession)
window?.rootViewController = UIHostingController(rootView: weekView)
No i realize that it has become a complete mess.. It's time for me to rethink this..
How do you handle navigation in apps where it can't be always done by pushing/popping the views from Navigation stack?
Using ViewBuilders is a good option here.
@ViewBuilder func myViewRouter(selection: Selection) -> some View {
switch selection {
case selection1:
View1()
case selection2:
View2()
case selection3:
View3()
}
}
enum Selection { ... }
ViewBuilders are powerful, its pretty much a function that can return opaque types but notice the lack of the return keyword. This seems like a perfect use case for it. In the example I used a enum but its also common to see this used with a var selection = 0 on the parent view and have the ViewBuilder as the child. Either way, same functionality.
Below is is a good url to understand ViewBuilders.
https://swiftwithmajid.com/2019/12/18/the-power-of-viewbuilder-in-swiftui/
Last edit: Here is an example use case:
import SwiftUI
struct ContentView: View {
@State private var selection: SelectionEnum = .zero
var body: some View {
VStack {
showMyViews(selection: selection)
HStack {
ForEach(SelectionEnum.allCases, id: \.self) { selection in
Button(action: {self.selection = selection}){
Text(selection.rawValue)
.fontWeight(.bold)
.frame(width: 60, height: 60)
.foregroundColor(.white)
.background(Color.blue)
.cornerRadius(10)
}
}
}
}
}
@ViewBuilder func showMyViews(selection: SelectionEnum) -> some View {
switch selection {
case .zero:
ViewA()
case .one:
ViewB()
case .two:
ViewC()
case .three:
ViewD()
}
}
enum SelectionEnum: String, CaseIterable {
case zero
case one
case two
case three
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct ViewA: View {
var body: some View {
Text("View A")
}
}
struct ViewB: View {
var body: some View {
Text("View B")
}
}
struct ViewC: View {
var body: some View {
Text("View C")
}
}
struct ViewD: View {
var body: some View {
Text("View D")
}
}