Skip to content

Instantly share code, notes, and snippets.

@Amzd
Last active Nov 23, 2021
Embed
What would you like to do?
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")
}
}
}
@sesencheg
Copy link

sesencheg commented Dec 29, 2020

Hello. Thx for solution, but:
...

@State var cartCount: Int = 0
...
.navigationBarItems(
trailing: (
NavigationLink(destination: CartView()) {
Image(systemName: "bag.fill")
.imageScale(.large)
.foregroundColor(Color.init(hex: "858ac1"))
}
.overlay(
Text(self.cartCount.description)
.foregroundColor(Color.white)
.font(.system(size: 10))
.frame(width: 15.0, height: 15.0)
.background(Color.init(hex: "e80063"))
.cornerRadius(15), alignment: .topTrailing)
)
)
...

if i change "cartCount", view didn't change...

@Amzd
Copy link
Author

Amzd commented Dec 29, 2020

And without my code it works?

@sesencheg
Copy link

sesencheg commented Dec 29, 2020

And without my code it works?

Yes

@Amzd
Copy link
Author

Amzd commented Dec 29, 2020

Could you please edit your comment to correct the code block formatting, it’s hard to read on mobile.

@amosavian
Copy link

amosavian commented Sep 19, 2021

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