Search code examples
swiftxcodecocoansscrollviewmagic-mouse

NSTextView inside NSScrollView not co-operating while scrolling


I have a TableView which has NSTextView as cells. this is a situation where I have scrollView inside scrollView. Now when I scroll the contents of the textView, and when the textview's content reaches the end, I want the parent scrollView ( the tableView ) to continue scrolling. But by default this does not happen. Instead the parent doesn't scroll at all when the mouse pointer is inside the textView.

I want to achieve something like in this example.

This is my solution:

public class DisableableScrollView: NSScrollView {

public override func scrollWheel(with event: NSEvent) {

    // Check if the text field is empty
    if (self.subviews[0].subviews[2] as! NSTextView).textStorage?.length == 0 {
        nextResponder?.scrollWheel(with: event)
    }
    // Bottom
    else if self.verticalScroller?.floatValue == 1.00  {
        if event.deltaY < 0 {
            nextResponder?.scrollWheel(with: event)
        }
        else {
            super.scrollWheel(with: event)
        }
    }
    // Top
    else if self.verticalScroller?.floatValue == 0.00  {
        if event.deltaY > 0 {
            nextResponder?.scrollWheel(with: event)
        }
        else {
            super.scrollWheel(with: event)
        }
    }

    else {
        super.scrollWheel(with: event)
    }
}

But there is a problem: when I scroll on one text field other text field is scrolling.click here to see

Here the problem is with Magic mouse. If I use a normal mighty mouse, everything works fine. But with magic mouse, when I lift my finger after scrolling, it continues to scroll ( momentum scroll ) but scrolls wrong textView instance sometimes. As per Apple Documentation, there are two properties for a scrollwheel event : phase and momentumPhase. With magic mouse after I lift my finger up phase becomes Ended and momentumPhase becomes Began.

Does anyone know a standard solution to this problem? Or if my code is correct what might be going wrong?


Solution

  • I found the solution to my problem and hence thought of sharing it.

    This particular method wantsForwardedScrollEvents(for:) can be used for forwarding the scroll events up the responder chain whenever the content has reached the end. We just have to override this method and return true wherever necessary.