cocoaappkitnsscrollviewnseventikimagebrowserview

NSEventPhaseEnded not called on NSScrollView with IKImageBrowserView


I have an IKImageBrowserView embedded within an NSScrollView, to help test this problem the IKImageBrowserView only fills half the of width of the NSScrollView.

My NSScrollView subclass implements the following method and logs when a scroll began and ended on the scrollview.

- (void)scrollWheel:(NSEvent *)event {
    switch (event.phase) {
        case NSEventPhaseBegan:
            NSLog(@"NSEventPhaseBegan");
            break;
        case NSEventPhaseEnded:
            NSLog(@"NSEventPhaseEnded");
            break;
    }

    [super scrollWheel:event];
}

The NSEventPhaseBegan event phase successfully calls whether the cursor is over the IKImageBrowserView or not when you start scrolling. This is the expected behaviour.

But NSEventPhaseEnded event phase is not called when the cursor is over the IKImageBrowserView when you stop scrolling. If the cursor is not over the IKImageBrowserView then NSEventPhaseEnded does get called.

Why is the IKImageBrowserView preventing NSEventPhaseEnded being called on my NSScrollView?


Solution

  • Spoke to a helpful engineer at Apple who told me this behaviour is in fact a bug. ImageKit is eating some scrollWheel events unfortunately. As a workaround, subclass the IKImageBrowserView, implement scrollWheel and forward the event both to "super" and the enclosing scrollview.

    @implementation MyImageBrowserView
    
    - (void)scrollWheel:(NSEvent *)theEvent {
       [super scrollWheel:theEvent];
    
       if ([theEvent phase] == NSEventPhaseEnded) 
           [[self enclosingScrollView] scrollWheel:theEvent];
       }
    }
    
    @end