Skip to content

Instantly share code, notes, and snippets.

@Amzd
Last active July 6, 2023 03:34
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Amzd/67bfd4b8e41ec3f179486e13e9892eeb to your computer and use it in GitHub Desktop.
Save Amzd/67bfd4b8e41ec3f179486e13e9892eeb to your computer and use it in GitHub Desktop.
Fix the back swipe gesture not working correctly in SwiftUI. https://stackoverflow.com/a/58345554/3393964
/// Fixed swipe gesture NavigationLink
struct NavigationLink<Destination: View, Label:View>: View {
var destination: Destination
var label: () -> Label
public init(destination: Destination, @ViewBuilder label: @escaping () -> Label) {
self.destination = destination
self.label = label
}
/// If this crashes, make sure you wrapped the NavigationLink in a NavigationView
@EnvironmentObject private var nvc: NavigationViewUINavigationController
var body: some View {
Button(action: {
let rootView = self.destination.environmentObject(self.nvc)
let hosted = UIHostingController(rootView: rootView)
self.nvc.pushViewController(hosted, animated: true)
}, label: label)
}
}
/// Fixed swipe gesture NavigationView
struct NavigationView<Content: View>: UIViewControllerRepresentable {
var content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func makeUIViewController(context: Context) -> UINavigationController {
let nvc = NavigationViewUINavigationController()
let host = UIHostingController(rootView: content().environmentObject(nvc))
nvc.viewControllers = [host]
return nvc
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
}
/// Fileprivate type to not expose the navigation controller to all views
fileprivate class NavigationViewUINavigationController: UINavigationController, ObservableObject {}
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 30) {
NavigationLink(destination: Text("Detail"), label: {
Text("Show detail")
})
Button(action: {
self.isPresented.toggle()
}, label: {
Text("Show modal")
})
}
.navigationBarTitle("SwiftUI")
}
.edgesIgnoringSafeArea(.top)
.sheet(isPresented: $isPresented) {
Modal()
}
}
}
struct Modal: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 30) {
NavigationLink(destination: Text("Detail"), label: {
Text("Show detail")
})
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text("Dismiss modal")
})
}
.navigationBarTitle("Modal")
}
}
}
@amosavian
Copy link

This code works without overriding NavigationLink, NavigationView is enough. @Amzd

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment