Canceling a swipe back will cause the view action to stop working with SwiftUI

Viewed 55

It uses navigation that allows you to go back even if you swipe the middle of the screen as shown in the code here. In this case, if a SwiftUI view exists in the viewControllers of the navigation, the SwiftUI view will not accept the action if you cancel the return operation in the middle. Is there a solution to this?

https://gist.github.com/policante/33a2d11b0501052d230c1f213dcacde3

class BaseNavigationController: UINavigationController, UINavigationControllerDelegate {
    
    var interactivePopTransition: UIPercentDrivenInteractiveTransition!
    
    override func viewDidLoad() {
        self.delegate = self
    }
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        addPanGesture(viewController)
    }
    
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
        if operation == .pop {
            return NavigationPopTransition()
        }else{
            return nil
        }
        
    }
    
    func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
        if animationController.isKind(of: NavigationPopTransition.self) {
            return interactivePopTransition
        }else{
            return nil
        }
    }
    
    private func addPanGesture(_ viewController: UIViewController){
        let popRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanRecognizer(recognizer:)))
        viewController.view.addGestureRecognizer(popRecognizer)
    }
    
    @objc func handlePanRecognizer(recognizer: UIPanGestureRecognizer){
        var progress = recognizer.translation(in: self.view).x / self.view.bounds.size.width
        progress = min(1, max(0, progress))
        print(progress)
        if recognizer.state == .began {
            self.interactivePopTransition = UIPercentDrivenInteractiveTransition()
            self.popViewController(animated: true)
        }else if recognizer.state == .changed {
            interactivePopTransition.update(progress)
        }else if recognizer.state == .ended || recognizer.state == .cancelled {
            if progress > 0.2 {
                interactivePopTransition.finish()
            }else{
                interactivePopTransition.cancel()
            }
            interactivePopTransition = nil
        }
    }
}
struct SampleView: View {
    var body: some View {
        NavigationLink(
            destination: SampleView(),
            label: {
                Text("LINK")
            })
    }
}

let view: UIHostingController = UIHostingController(rootView: SampleView())
let nav = BaseNavigationController[enter image description here][1](rootViewController: view)
present(nav, animated: true, completion: nil)

Reproduced gif

0 Answers
Related