Panning multiple scroll views simultaneously

UIScrollView provides a lot of control over the way you can present content to the user, but I have a need for one gesture recognizer to pan  multiple views simultaneously. You can probably use scrollRectToVisible to achieve this by moving the content view programmatically, but implementing the bouncy physics via that method seems painful. Plus I have other customizations I want to make.

In search of a solution, I found Ole Begemann’s outstanding post Understanding UIScrollView on reproducing the functionality of UIScrollView. The idea behind the article was to achieve a better understanding of how this Cocoa feature works, but for this iOS newbie it was a way to produce the behavior I needed.

The original post is excellent so there’s little point in me saying much else about it, other than that I am working in Swift and thus needed an implementation in that language. You can get my implementation on GitHub. I have not yet implemented the inertial scrolling, bouncing and rubber banding that some of Ole’s readers contributed, but I’ll update this post when that work is done.

The benefit of making your own view is that you can determine how that view handles gestures (actually, you can still do this if you subclass UIScrollView, but I’ll get into that later). In this case, I don’t want my custom scroll view to handle gestures at all. So while Ole’s class calls addGestureRecognizer to set one of its own methods as its gesture action handler, my SwiftScrollView.handlePanGesture() is called by its superview (in the example on GitHub this superview is just the ViewController):

And of course the superview sets a UIPanGestureRecognizer so its version of handlePanGesture gets called:

There you have it: one gesture recognizer scrolling two views. If you run the project I have up on GitHub you can see this in action. There’s more stuff I want to do with this and I’ll share that soon.

P.S.: If you want to do something like this but still want features of UIScrollView, you can subclass it and override addGestureRecognizer so it can’t set a pan recognizer:

Pretty crude, but it works. You might also be able to do something like

after self.panGestureRecognizer is set, but I haven’t tried this.