import SwiftUI
struct ConditionalNavigationParentView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
var body: some View {
NavigationView {
// iPhone Portrait
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
VStack {
Text("This is the Parent View.")
.foregroundColor(Color.black)
.font(.headline)
NavigationLink(destination: ConditionalNavigationChildView()) {
Text("Navigate to Child View.")
.font(.body)
}
}
}
// iPhone Landscape
if verticalSizeClass == .compact {
HStack {
Text("This is the Parent View.")
.foregroundColor(Color.black)
.font(.headline)
NavigationLink(destination: ConditionalNavigationChildView()) {
Text("Navigate to Child View.")
.font(.body)
}
}
}
}
}
}
struct ConditionalNavigationChildView: View {
var body: some View {
Text("This is the Child View.")
.font(.headline)
}
}
In the above code, we have a Parent View and a Child View. The parent view holds a conditional title and navigation link. The child view holds a title. When you navigate to the child view, navigation works fine. However, once the condition that holds the navigation link in the parent view is no longer met (by rotating your device from portrait to landscape), the connection keeping the child and parent views navigatable breaks, and forces navigation back to the parent view. This appears to be because SwiftUI as it is now needs to redraw the components from the parent view. With the example above, one solution would be to make only the text condtional, and have the navgation link be held in both a vstack and hstack simultaneously, like this:
import SwiftUI
struct ConditionalNavigationParentView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
var body: some View {
NavigationView {
VStack {
// iPhone Portrait
if horizontalSizeClass == .compact && verticalSizeClass == .regular {
Text("This is the Parent View.")
.foregroundColor(Color.black)
.font(.headline)
}
HStack {
// iPhone Landscape
if verticalSizeClass == .compact {
Text("This is the Parent View.")
.foregroundColor(Color.black)
.font(.headline)
}
NavigationLink(destination: ConditionalNavigationChildView()) {
Text("Navigate to Child View.")
.font(.body)
}
}
}
}
}
}
struct ConditionalNavigationChildView: View {
var body: some View {
Text("This is the Child View.")
.font(.headline)
}
}
While this does fix the navigation issue in this case, other cases with multiple navigation links seem to be completely impossible. For example, say you replace the title with another navigation link. The second one will still work fine, as it is not conditional, but the first one, and all of its subviews, will get pushed back to the parent view on rotation.
In UIKit, this would never be a problem, as conditional navigation doesn't push back to the parent view like that. So is this a SwiftUI bug? Or is it intended behavior? If it is intended behavior, what solution is there for a view with multiple conditional navigation links?