Avoid SwiftUI code duplication for different views embedded within a NavigationView

95 Views Asked by At

I'm using the following code in order to display a view that works with Vision framework. The view is embedded within a NavigationView that presents a title and a button to dismiss the presented view.

.sheet(isPresented: $isVisionPresented) {
#if targetEnvironment(simulator)
    NavigationView {
        Text("Cannot run Vision framework in Simulator")
            .navigationTitle("Sample title")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                Button("Close") {
                    isVisionPresented = false
                }
            }
    }
#else
    NavigationView {
        VisionView()
            .navigationTitle("Sample title")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                Button("Close") {
                    isVisionPresented = false
                }
            }
    }
#endif
}

Since Vision framework is not available in Simulator, I'm using targetEnvironment(simulator) to display a dummy view just for test purposes.

Is there any smart way to avoid duplicated code for that part that is common between the two views? It's worth to note that VisionView implements UIViewControllerRepresentable.

.navigationTitle("Sample title")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
    Button("Close") {
        isVisionPresented = false
    }
}
1

There are 1 best solutions below

0
Lorenzo B On

I've ended up with the following solution leveraging [ViewModifier][1].

struct NavigationBar: ViewModifier {
    @Binding var isPresented: Bool
    
    let navigationTitle: String
    let buttonTitle: String
    
    func body(content: Content) -> some View {
        content
            .navigationTitle(navigationTitle)
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                Button(buttonTitle) {
                    isPresented = false
                }
            }
    }
}

extension View {
    func navigationBar(isPresented: Binding<Bool>, navigationTitle: String, buttonTitle: String) -> some View {
        modifier(NavigationBar(isPresented: isPresented, navigationTitle: navigationTitle, buttonTitle: buttonTitle))
    }
}

that can be used like the following:

Text("Cannot run Vision framework in Simulator")
    .navigationBar(isPresented: $isVisionPresented, navigationTitle: "Dummy title", buttonTitle: "Close")