A Quick Commentary on UIScrollView

Over the past few months, I've been working on an iOS application laden with scroll views. Because of the fluid and interactive design, I needed to make sure multiple instances of UIScrollView and its subclass, UICollectionView, worked together seamlessly.

Often times, as one view moved, one or more others also needed to move. This can be facilitated by using scrollViewDidScroll:, but you have to be careful when updating subsequent scroll views. Why? Well, the normal method for updating a scroll view to a particular location setContentOffset:animated: also invokes scrollViewDidScroll:. You can see why this might be a problem...

Our friends over at objc.io have given a thorough and excellent overview of how UIScrollView works under the hood (I highly recommend the read). Long story short, contentOffset and consequently, setContentOffset:animated:, are made up! They don't actually exist on their own—they're simply wrappers around the bounds of a scroll view.

setContentOffset:animated: is actually just updating bounds.origin to the CGPoint provided and optionally animating this update. It's also invoking that delegate method that would normally be causing us problems. So how do we get around this? Simply update the bounds directly!

tl;dr: Update bounds.origin directly instead of using setContentOffset:animated: to avoid invoking scrollViewDidScroll:.

Content Inset

Another important property of UIScrollView is contentInset. By using this property, we're able to add (and also remove, should you need to) blank space to our scroll view on any of its sides.

This can be useful when the onscreen keyboard displays over an input form, for example. Instead of mucking with the frame or with auto layout constraints, simple update the contentInset: when the keyboard shows, add the keyboard's height to the bottom; when the keyboard hides, subtract its height from the bottom.

Besides the above example, I also used this property, in conjunction with a clear background, to display custom hero graphics in a recent application, allowing the content to scroll on top of them.

Demo App

I put together a super simple app to demonstrate visually (and in code) these concepts, which will hopefully clarify anything I missed. It has a horizontal scroll view containing an image from a recent trip to Death Valley, textual representation of contentOffset and bounds.origin (you'll see they're the same), and a slider for modifying contentInset.

Check out the code on Github here.

As always, feel free to reach out on Twitter @jonathonstaff if you have any questions/feedback.

Recommended reading: Understanding Scroll Views and Apple's Documentation on UIScrollView.