Tip

How to Use the UINavigationController Swipe Back Gesture with a UIPageViewController

I’ve been working on an app at work that’s “Snapchat-eqsue” (uses a UIPageViewController to page between a full-screen camera and a UINavigationController) when I came across this conundrum. Basically, the app is setup as follows:

Please excuse the poor lighting and shoddy sketch. It's early and I didn't feel like opening Sketch.
Please excuse the poor lighting and shoddy sketch. It’s early and I didn’t feel like opening Sketch.

So the Camera is the leftmost view in the PageViewController and the UINavigationController, along with all the views it will add to its stack, is on the right. Things got a bit tricky though when our designer wanted to avoid using physical back buttons on the navigation stack and have the traditional swipe back take you to the previous page. My first instinct was to intercept the PageController gestures, but when it’s set to scrolling, those don’t actually exist–the gesture array comes up empty. That’s when I came up with this fun little hack that’s incredibly easy to do.

The tl;dr is you disable the UIPageViewController’s UIScrollView when the NavigationController displays any view that’s not the root view controller and add a swipe gesture recognizer to each of the subviews. While this sounds like a lot of tedious work, it’s actually really easy if you just subclass UIViewController and use that app-wide (which is actually nice for a variety of reasons like themeing–but that’s for another post).

Anyway, here’s what I did step by step:

1. Made a global helper file and added this handy method to it to allow me to easily toggle the scroll state for any UIPageViewController I pass into it.

***

2. I added the following lines of code to the root ViewController of my NavigationController. Basically, any time the root ViewController comes back on screen, I re-enable the scrolling on the PageViewController so that it intercepts swipe gestures again.

***

3. Anywhere I’m showing a new ViewController on the navigation stack, I added the following line of code (for instance in my case I added it to DidSelectRowAtIndexPath on a UITableView). This turns off scrolling for the PageViewController and lets my custom gesture take precedence.

***

4. Subclassed UIViewController and added the following lines of code. All this does is add a swipe gesture that pops the current view from the navigation stack. Just be sure to make any UIViewController you plan to push onto the navigation stack a subclass of the class you create and you’re golden.

I’d be curious to know if anyone else has come up with another way to do the same thing. This felt like the most straight forward way to me while also having the added benefit of being easy to implement and remove if necessary later on in the app’s lifecycle. It also doesn’t seem to affect performance in any major way (how users like the UX is another thing entirely, and something we haven’t had a chance to test yet). Hopefully, though this trick will help someone else out. I’ll admit, I felt a little clever when I came up with it.

One thought on “How to Use the UINavigationController Swipe Back Gesture with a UIPageViewController”

  1. leonardo lombardi says:

    thanks for sharing

Leave a Reply

Your email address will not be published. Required fields are marked *