Search code examples
objective-ccocoacore-animationnsviewnsscrollview

NSScrollView with CA layer mask adds a second useless scrollbar


I added a custom NSScrollView for a table, and in order to keep everything masked within the window shape I used core animation layer masks to clip it and it's subviews like so:

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    CGMutablePathRef cgPath = CGPathCreateMutable();

    //Make path here

    [maskLayer setPath:cgPath];

    self.wantsLayer = YES;
    self.layer.mask = maskLayer;
    self.layer.masksToBounds = YES;
}

However whilst the mask itself works fine, it gives me this cloned 'ghost' scrollbar on the other side: scrollbar

The majority of the scrollbar is covered by the table itself, but I've shifted a cell view over a bit to show how it continues downwards. The scrollbar is the same size as the one on the right and doesn't move or respond to clicking or scrolling.

When I hide the window and reopen it however, it's gone completely. Is it something to do with the scrollbar not being redrawn correctly?


Solution

  • Since I had loaded the view from XIB and since this doesn't require constant drawing, instead of calling this from initWithFrame or drawRect, I should have called this from awakeFromNib:

    - (void)awakeFromNib {
        [super drawRect:dirtyRect];
    
        CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
        CGMutablePathRef cgPath = CGPathCreateMutable();
    
        //Make path here
    
        [maskLayer setPath:cgPath];
    
        self.wantsLayer = YES;
        self.layer.mask = maskLayer;
        self.layer.masksToBounds = YES;
    }