Search code examples
objective-cnstableviewnscellnstableviewcell

NSCell redrawing issues


I'm creating a NSCell subclass that draws some objects directly onto the view (using drawInRect:fromRect:operation:fraction:respectFlipped:hints:) and also draws an NSButton instance simply using NSView's addSubview: selector.

While objects drawn using the first method all draw correclty, I'm having problems with drawing the NSButton correctly. The issue is that my NSButton instances will draw in the right places, but multiple times over.

I've researched this on the internet for a while and some people suggested using a cache, but I'm not sure if this is efficient. (going an array containing buttons using a for loop will definately cause slow scrolling since I display a lot of data...)

How would you do this? Am I barking up the wrong tree?

This is the relevant code:

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{    
    NSRect _controlRect = cellFrame;

    float _Y = cellFrame.origin.y;

    NSRect _accessoryRect = NSMakeRect(_controlRect.size.width - 70.0f, _Y + 9.0f, 50.0f, 23.0f);

    _switch = [self _choiceSwitch];

    [_switch setFrame:_accessoryRect];
    [controlView addSubview:_switch];
}

Solution

  • Long story short: Friends don't let friends addSubview, while drawing.

    This a fundamental, and not particularly well-explained aspect of managing control interfaces, but is important to come to grips with.

    Let your controllers dictate the "order" of subviews, and you can sleep tight knowing that that button shouldn't get overtly mucked about (which is NOT the case if it's getting jostled around inside your custom drawing routines).

    It's easy to get trapped in this alley, cause, like, hey, I added an NSImageView in my initWithFrame and everything seems to be okay… But it's just sort of not how you're supposed to do it, I guess… and when you start subclassing NSControl, etc. is when you start to realize why.

    Updated: Here's a really good write up on designing custom controls with an equally as great sample project attached - which embodies the kind of code organization that can help avoid this type of issue. For example.. you'll notice in the controller class how he's keeping each button seperate, unique, and independent of other views' business…

    for (int butts = 0; butts < 3; butts++) {
        NSRect buttFrame = NSMakeRect(0, butts * 10, 69, 10);
        ExampleButt *butt = [[ExampleButt alloc]initWithFrame:buttFrame];
        [mainView addSubview:butt];
    }
    

    enter image description here