Context:
Apple has "soft-deprecated" NSCell on macOS. I'm trying to reduce the use of it in my custom NSControl subclasses and, instead, use CALayers to handle my drawing. To do this, I make my NSButton subclass layer-backed:
self.wantsLayer = YES;
And then I attempt to handle my drawing using the "updateLayer" path instead of "drawRect":
- (BOOL) wantsUpdateLayer {
return YES;
}
- (void) updateLayer {
// Change layer background/border colors if pressed, disabled, etc.
// Change text color of a CATextLayer sublayer for button's title.
}
The Problem:
If I use -updateLayer, the NSCell still receives drawing commands and draws its title, resulting in a "blurry" title string in my control because the string is being drawn twice—once in my textLayer and once by the Cell.
If, however, I do the exact same work as above in -drawRect: instead of -updateLayer, then the cell does NOT do any drawing (because I don't call down into it with [self.cell drawInteriorWithFrame:ControlView:])
I cannot, for the life of me, figure out what's firing the cell drawing when the associated controlView (my button subclass) has opted into -updateLayer instead of -drawRect:.
I have looked at all the methods on NSControl.h and NSView.h. I've overridden all of the -updateCell and associated methods. None of those are the culprit. I cannot simply set self.cell=nil because NSControl still relies on NSCell for event handling, etc.
Can someone tell me how to stop NSCell from drawing when its associated controlView is using -updateLayer instead of -drawRect:?
In
-[NSButtonCell layoutLayerWithFrame:inView:], the cell adds aNSTextFieldto draw the title. OverridetitleRectForBounds:and returnNSZeroRectto remove the title.