Implementing Interactive Pop Gesture in iOS

Adam Wareing
Level Up Coding
Published in
3 min readApr 14, 2020

--

The interactive pop gesture is a core interaction that makes navigating back to the previous screen so much easier. And the bigger the device gets, the more value it delivers.

Apple claims this is the default behaviour that comes out of the box, which is true for a standard app. Although, if you are building a custom app, as I find myself doing the majority of the time, you will find that this is no longer applicable.

For example, if you have a custom back button, or don’t want the user to navigate back from a certain screen you have no control with the default implementation. In this article, we will walk through implementing it in a way that lets you have full control over whether the user should be able to navigate back from a screen.

When can the screen navigate back?

In our BaseViewController which all view controllers in the app subclass, we add a default function to determine if the screen should navigate back. Some apps may not have a BaseViewController, which if is true for you, you can skip this step. Although, I would recommend considering adding one in to provide screens access to common functionality. In our case, we have a function that determines if this screen should prevent navigating back. We allow the screen to navigation back when the following conditions are met:

  • The navigation bar is visible
  • The custom back button is visible
  • The screen isn’t showing a loader

This is shown in the snippet below.

When can the navigation controller navigate back?

This requires having a subclassed UINavigationController used across the app, or at least in the places you want to implement the pop gesture functionality. The app I was adding it to was already in production and didn’t have one so I replaced all manual creations of a UINavigationController with a newly created BaseNavigationController.

This has a stored property duringPushAnimation which allows us to track when a screen is being animated onto the stack of view controllers.

You can see that we set two delegates in the viewDidLoad function. The first one is needed as we need to know when a screen has finished been pushed onto the stack of view controllers. The second is the gesture recogniser for the pop gesture. We conform to the protocols in the next step.

Implementing UINavigationControllerDelegate

I personally like to confirm a class to a protocol using an extension per protocol. This neatly separates different concerns, encourages related logic to be grouped, and makes it easier for another developer to read. By implementing this delegate function it gives us insight into when a UIViewController has shown.

Implementing UIGestureRecognizerDelegate

This is where all the magic happens, this is where we decide to allow whether or not the user can navigate back. There are three main situations where we don’t want them to navigate back.

  • If the view controller doesn’t want to allow it. This can be done by calling the preventInteractivePopGesture function we wrote earlier on the base view controller
  • When there is only one screen on the stack
  • Or if we are during a push animation which is when a screen is animating on. If we allowed the user to go back during this time it could jumble the ordering of the screens.

There you have it

Now you should have an awesome interaction in your app that allows users to swipe from the left edge of their screen to navigate back to the previous one. Since recently upgrading my iPhone, the screen has gotten considerably larger and I find myself using this feature even more than I did previously.

Fortunately, this feature isn’t hard to implement once you knew what to do. I found a massive lack of resources online for implementing this in a custom app and it took a little bit of trial and error to get here. Although after implementing this in two considerable apps in production I can confirm that it works like a charm. Hopefully, this has taught you something new and can save you time when you decide to implement it in your app.

--

--