I'm using scrollWheel(with:) rather than NSPanGestureRecognizer
The scrollWheel(with:) method is really what it says on the tin. It's for supporting the scroll wheel on your mouse. Then when Apple got rid of the physical scroll wheel on the mouse and replaced it with a touch-sensitive mouse, it became a half-way gesture. And as you have seen, it's halfway supported.
as far as I'm aware, AppKit's NSPanGestureRecognizer can recognize drags but not scrolls (please correct me if I'm wrong)
I don't know if you're wrong, because I've never used that API either. I used the older, mouse-based methods. But you don't want to fall into API dependency. That seems pretty common these days. If Apple doesn't provide some clearly named method or enum for something, people assume it's impossible. It's never impossible. A pan gesture requires touching the trackpad. That makes it a drag. You can reposition the view from that.
But that's really getting off-topic. The main point is that you're somehow triggering some odd behaviour by attempting to use only scrollWheel(with:). I've never seen what you're describing.
I took another look at your demo app. This time, I did what I should have done the first time. I ripped out the vast majority of your code and replaced it with the equivalent structures in InterfaceBuilder. I kept the livescroll notificiations. I also kept the custom scroll view with the no-op override. No problem. No scrolling artifacts. All notifications arrive as expected. My best guess is that somehow you didn't setup scrolling elasticity correctly. Or perhaps it was something else about the scroll view. I don't know.
I normally don't setup scrollview hierarchies in code. But it just so happens that I am doing that now, so I'll take another look at the problem your describing once I get to a point where I can test it.
Topic:
UI Frameworks
SubTopic:
AppKit