Search code examples
swiftswiftuinavigationstatenavigationview

How to change the Navigation View Style of a Navigation View depending on a @State in SwiftUI?


I am currently working with Navigation View in SwiftUI.

Problem: I would like to change the Navigation View Style from an Descendent View using @State & @Binding.

@Binding var defaultNavigationStyle: Bool
    
var body: some View {
    NavigationView {
        sidebar
            
        Text("Choose an Option from the Sidebar.")
            
        Text("Select an Element.")
    }
    .navigationViewStyle(defaultNavigationStyle ? DefaultNavigationViewStyle() : StackNavigationViewStyle())
}

Obviously, this does not work since the Elements have different Types. Error Message: Result Values in '?:' expression have mismatching types 'DefaultNavigationViewStyle' and 'StackNavigationViewStyle'

Question: How can I change the Navigation View Style using @State & @Binding, without creating a completely different NavigationView and loosing all the State?


Solution

  • You can use a conditional modifier:

    extension View {
        typealias ContentTransform<Content: View> = (Self) -> Content
    
        @ViewBuilder
        func conditionalModifier<TrueContent: View, FalseContent: View>(
            _ condition: Bool,
            ifTrue: ContentTransform<TrueContent>,
            ifFalse: ContentTransform<FalseContent>
        ) -> some View {
            if condition {
                ifTrue(self)
            } else {
                ifFalse(self)
            }
        }
    }
    

    and apply it to the NavigationView:

    NavigationView {
        sidebar
        Text("Choose an Option from the Sidebar.")
        Text("Select an Element.")
    }
    .conditionalModifier(
        defaultNavigationStyle,
        ifTrue: { $0.navigationViewStyle(DefaultNavigationViewStyle()) },
        ifFalse: { $0.navigationViewStyle(StackNavigationViewStyle()) }
    )