I’ve been playing with having a view whose sole job at the moment is to display a single rectangular swatch of colour. Sounds a perfect job for the convenience and speed of UIView.backgroundColor, right?
So I go ahead and implement my view to simply set its background color to the desired appearance. Whack it in a table view cell and we’re all looking good. Great.
But what’s this? When the cell is highlighted/selected, my custom view disappears! Why is this?
As a conscientious developer, you might have gone through at some and assigned your views a background color that matches their cell. This allows them to be rendered opaquely, saving Core Animation the work of performing layer blending.
But, during selection, it’s desirable that your carefully chosen background colour go away. Otherwise, your cell would likely appear to contain ugly great splotches of white!
Helpfully, UITableViewCell has your back here: it traverses through all its descendant views and adjusts their background colour accordingly (I believe to UIColor.clearColor, although potentially it could use the same colour as the selection highlight itself). After selection, the same trick is performed again in reverse, putting all the backgrounds back as they used to be.
But in our case, we’re using the background colour to display useful information rather than as an actual background. The swap is undesirable. Of course this is a problem that has struck many an iOS Developer to date, and has plenty of coverage on Stack Overflow.
Two fairly common solutions seem to be:
- After highlighting, have your UITableViewCell subclass undo the damage done by super
- Turn off the cell’s natural highlighting and re-implement yourself
- Override -drawRect: to perform the colouring instead
I find neither of the first two particularly elegant. I’m also keen to avoid implementing -drawRect: if I can, since then Core Animation has to kick in a considerable extra amount of machinery to manage a buffer for me to draw into.
Instead, I reason that any code — be it Apple’s or mine — that adjusts the background colour of this custom view is in the wrong. It’s nice and simple then to override -setBackgroundColor: to be a no-op (and of course document this in the header).