4

My swipe to go back feature works but only works on the edge of the screen. How can I have it work from anywhere on the screen?

  • Please do share some code. Also what UIGestureRecognizer you are using? and what state? PLEASE CODE ! – Korpel Oct 02 '15 at 19:00

3 Answers3

21

It's actually quite easy to do on the UINavigationController subclass without any intervention into every UIViewController subclass pushed. Also respecting built-in swipe-from-edge state (so when it's disabled intentionally, the new gesture is disabled as well):

import UIKit

class NavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()
        setupFullWidthBackGesture()
    }

    private lazy var fullWidthBackGestureRecognizer = UIPanGestureRecognizer()

    private func setupFullWidthBackGesture() {
        // The trick here is to wire up our full-width `fullWidthBackGestureRecognizer` to execute the same handler as
        // the system `interactivePopGestureRecognizer`. That's done by assigning the same "targets" (effectively
        // object and selector) of the system one to our gesture recognizer.
        guard
            let interactivePopGestureRecognizer = interactivePopGestureRecognizer,
            let targets = interactivePopGestureRecognizer.value(forKey: "targets")
        else {
            return
        }

        fullWidthBackGestureRecognizer.setValue(targets, forKey: "targets")
        fullWidthBackGestureRecognizer.delegate = self
        view.addGestureRecognizer(fullWidthBackGestureRecognizer)
    }
}

extension NavigationController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        let isSystemSwipeToBackEnabled = interactivePopGestureRecognizer?.isEnabled == true
        let isThereStackedViewControllers = viewControllers.count > 1
        return isSystemSwipeToBackEnabled && isThereStackedViewControllers
    }
}
rshev
  • 4,086
  • 1
  • 23
  • 32
  • Hey. How would you avoid `fullWidthBackGestureRecognizer` taking precedence over other recognizers? For instance, the recognizers for `UIContextualAction` are ignored completely while using this method. They (recognizers of the tableview) are also not directly accessible / it's a private API... thus, we can't really use them in the `UIGestureRecognizerDelegate` methods of the navigation controller. Any clues on what to do? Otherwise it works great, thanks! – David Feb 14 '21 at 22:14
  • Vertical scrolling not working with this solution. – Cristi Băluță Aug 14 '21 at 16:24
  • Sweettttttttt!!!!!! AWESOME answer! I had a couple of implementations of this before from somewhere on Github, but those are having issues. I haven't tested this thought with scrollViews. – Glenn Posadas Nov 13 '21 at 03:53
  • Does anyone happen to know how to implement this in SwiftUI? The NavigationLink in SwiftUI only lets you swipe back on the edges as well. – Hiro Jun 08 '22 at 21:41
3

Apple says here :

interactivePopGestureRecognizer

The gesture recognizer responsible for popping the top view controller off the navigation stack. (read-only)

@property(nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer

The navigation controller installs this gesture recognizer on its view and uses it to pop the topmost view controller off the navigation stack. You can use this property to retrieve the gesture recognizer and tie it to the behavior of other gesture recognizers in your user interface. When tying your gesture recognizers together, make sure they recognize their gestures simultaneously to ensure that your gesture recognizers are given a chance to handle the event.

So SloppySwiper library customise the UIPanGestureRecognizer.

Check out the library SloppySwiper, which achieves this by using UIPanGestureRecognizer and by recreating the default animation.

SloppySwiper:- UINavigationController delegate that allows swipe back gesture to be started from anywhere on the screen like instagram.

Usage of this library can be found here.

Cocoapods:- pod "SloppySwiper"

I test this library on ios7 and above. It works like a charm.

pkc456
  • 8,350
  • 38
  • 53
  • 109
-2

Swipe to go back is default behavior of pushed/showed view controllers. It works from left edge of the screen (by default). If you want to swipe back from any part of the screen, you should add UISwipeGestureRecognizer to your view:
let swipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: "didSwipe:") self.view.addGestureRecognizer(swipeGestureRecognizer)

K.K
  • 101
  • 3
  • 9
  • what do I have to add in the didSwipe function? –  Oct 02 '15 at 21:18
  • self.navigationController?.popViewControllerAnimated(true) – K.K Oct 03 '15 at 07:32
  • it works but I dont have the ability to control the slide like I do from the edge of the screen? –  Oct 03 '15 at 12:01
  • Ok so what you want is UIPanGestureRecognizer with custom transition between view controllers. Here you can find good answer with example how to do this: http://stackoverflow.com/a/22244990/5402342 – K.K Oct 03 '15 at 12:20