2

I have a custom box that I've made that is a subclass of NSBox. I override the drawRect: method and draw a gradient in it like this (assuming I already have a start & end color):

-(void)drawRect:(NSRect)dirtyRect {
    NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:start endingColor:end];
    [gradient drawInRect:dirtyRect angle:270];
    [gradient release];
}

Now this box is added as a subview of a prototype view for a NSCollectionView. In the view's original state it looks like this:

enter image description here

And after scrolling the view out of sight and back in again, it looks like this:

enter image description here

Why is my gradient getting corrupted like that, and how can I fix it? Thanks!

sudo rm -rf
  • 29,408
  • 19
  • 102
  • 161

2 Answers2

3

That dirtyRect argument doesn’t necessarily represent the entire box. If Cocoa decides that only a subframe of the original frame needs (re)drawing, dirtyRect represents only that subframe. If you’ve drawn a gradient for the entire frame and then (re)draw the same gradient for a subframe, it's likely they won't match.

Try:

[gradient drawInRect:[self bounds] angle:270];

instead.

One further note: it looks like your gradient object could be cached instead of being created/released inside -drawRect:.

1

Your problem is you're drawing in dirtyFrame, not the entire rectangle of the box. I have no idea if this is correct, but try this:

-(void)drawRect:(NSRect)dirtyRect {
    NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:start endingColor:end];
    [gradient drawInRect:[self bounds] angle:270];
    [gradient release];
}
icktoofay
  • 126,289
  • 21
  • 250
  • 231
  • You win the prize. Just needed to call `[gradient drawInRect:[self bounds] angle:270];` and it fixed the problem. Thanks! I'll accept it when it's availible. – sudo rm -rf Jun 24 '11 at 04:05
  • I'll update it to `[self bounds]` rather than `[self frame]`, I suppose, then. – icktoofay Jun 24 '11 at 04:11
  • Okay. I'll ask you the same question I asked Bavarious, namely is there a better place to be drawing this instead of in `drawRect:`? – sudo rm -rf Jun 24 '11 at 04:13
  • @sudo: Probably not. As far as I know, it will only be called when a previously-hidden part of the view is revealed, like when you scroll it back into view. If it's scrolled within the view or scrolled out but not back in, I don't think it will be called, so it should be fairly efficient. – icktoofay Jun 24 '11 at 04:16