Scrolling in NSScrollView stops when overwriting s

2019-02-25 20:29发布

问题:

I experience a weird bug when I overwrite the scrollWheel(theEvent: NSEvent) function in a NSScrollView.

Here's my code:

import Cocoa

class GraphScrollView: NSScrollView {
    var axisScrollViewInstance: AxisScrollView?

    override func scrollWheel(theEvent: NSEvent) {
        if theEvent.deltaY != 0 {
            axisScrollViewInstance?.scrollEventFromOtherScrollView(theEvent)
            super.scrollWheel(theEvent)
        } else if theEvent.deltaX != 0 {
            super.scrollWheel(theEvent)
        }
    }
}

class AxisScrollView: NSScrollView {
    var graphScrollViewInstance: GraphScrollView?
    override func scrollWheel(theEvent: NSEvent) {
        if theEvent.deltaY != 0 {
            super.scrollWheel(theEvent)
            graphScrollViewInstance?.scrollWheel(theEvent)
        }
    }

    func scrollEventFromOtherScrollView(theEvent: NSEvent) {
        if theEvent.deltaY != 0 {
            super.scrollWheel(theEvent)
        }
    }   
}

The code basically checks in which direction the user is scrolling and forwards the NSEvent to another NSScrollView if the direction is vertically. I need this so that I can have two NSScrollViews next to each other, which both scroll vertically and one of them scrolls horizontally as well. As an example you can look at the Mac Calendar app, which has an hour column on the left that only scrolls vertically and a week overview on the right that scrolls horizontally and vertically.

However, if I overwrite the scrollWheel-method and call the super function from inside, it leads to a weird problem with the Mighty Mouse. I can only scroll upwards and to the right, whereas it does nothing if I scroll in any other direction, although a NSEvent is always occurring, disregarding in which direction I scroll. After a while it stops scrolling altogether.

I have already tried to simply overwrite the scrollWheel-method and only call the super function with the event like this:

override func scrollWheel(theEvent: NSEvent) {
    super.scrollWheel(theEvent)
}

but it leads to the same problems. I have a second (non-Apple) mouse connected to my system, which has a 'normal' scroll wheel and with which my code works perfectly fine.

Do you have an idea what the problem could be? I heard that the NSEvents are of different subtype (1: Apple Device, 0: Any other Device). Maybe that has something to do with it? Otherwise, do you know how I can have two NSScrollViews next to each other that scroll vertically simultaneously?

回答1:

Okay, so it's a bug with the Interface Builder in Xcode 6.4 and maybe in earlier versions as well. You have to make sure that the box "Show Vertical Scroller" and "Show Horizontal Scroller" in the Attribute Inspector of the NSScrollView are checked.

If you check both boxes you won't have problems with overwriting the scrollWheel(theEvent: NSEvent) function. You can then remove the scroll bars programmatically again without problems by setting the hasHorizontalScroller and hasVerticalScroller to false in e.g. your init()


Update at 12.10.2015
I've reported the 'bug' to Apple, however it seems that by overwriting the -scrollWheel function, the view loses its responsive scrolling ability.

This is the answer of the Apple Dev Team:

  1. If you override -scrollWheel, then that scrollView cannot perform responsiveScrolling.
  2. If responsive scrolling is not on, then the scroller must be shown in order for scrollView to scroll.
  3. See Documentation for +isCompatibleWithResponsiveScrolling

In the documentation is says:

The default implementation of this method returns true unless the class overrides the lockFocus or scrollWheel: method