Alex Holyoakehttps://unsplash.com/photos/kgA5cRwr5IE

How scroll views work on macOS

Christoffer Winterkvist
hyperoslo
Published in
3 min readFeb 28, 2018

--

If you’ve ever developed an iOS application, I’m guessing that you’ve built a table- or collection view once or twice. You might also be familiar with the inheritance that both UI elements have. They both inherit from UIScrollView to gain their scrolling behavior. As you might have guessed, the same does not ring true for macOS. To add a scrolling experience for your users, you will have to implement an NSScrollView. It is not a non-trivial task but to make it smooth sailing you will have to understand the core concept of NSScrollView or rather, how to translate your iOS mindset over to the macOS domain.

An NSScrollView consists of two parts if you exclude the scroll view itself, an NSClipView and a document view. The document view is the only thing that you need to provide to get it to work.
I won’t go into too much detail as Apple has done an excellent job at providing how all the moving parts come together. For our example, the document view will be a simple NSView, but it could be a table- or a collection view.

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/NSScrollViewGuide/Articles/Basics.html

For these examples, I’ve decided to kick it up a notch by making them playground-friendly, simply copy the code into a playground and you should be able to tinker with the code as you please.

The first thing we do is to set up our custom view that we want to use as the document view for the scroll view. We give it a more prominent height than the scroll view to get it to scroll. The document views size works as the content size for the scroll view. So if you wanted horizontal scrolling, your document view should we wider than your scroll view.

For the sake of the playground giving a good example, we add a gradient to our custom view to make the scrolling more visible.

Because we want the scroll view to have an initial position located at the top, we need to provide this information to the content view, which is the clip view of the scroll view. Alternatively, we could also call the same method on the document view itself, but I tend to always invoke it on the content view as it is non-optional whereas the document view is not.

It might seem odd to set the content offset to the entire height of the subview’s frame. For more information about how frames work in macOS, you can head over and read one of my earlier articles. In that article we introduced a small trick to flip the views coordinates system, let’s apply the same here to see how we can change the implementation to make more sense for our iOS-centric way of looking at frames.

We now make a subclass of our NSView and set the property isFlipped to return true. Now we can simply set the content offset to start at zero which is much easier to reason about.

That’s it, fire up a playground and take it for a spin, the easiest way to experiment is to see it first hand. For more in-depth information about everything that NSScrollView has to offer then I suggest you head over to Apple’s documentation.

--

--

Christoffer Winterkvist
hyperoslo

random hero at @fink-oslo by day, cocoa vigilante by night, dad at dawn. my life is awesome. Previously @hyperoslo