If I set the backgroundColor attribute on a grouped UITableViewCell, the background color successfully changes. Great.
But I'd like to use UIAppearance to change the background color on all my UITableViewCells, so I can do it in one place and affect a change everywhere. Here's my code:
[[UITableViewCell appearance] setBackgroundColor:[UIColor colorWithRed:30.0/255.0 green:30.0/255.0 blue:30.0/255.0 alpha:1.0]];
UITableViewCell implements UIAppearance and UIAppearanceContainer, so I would have thought this would work. But it doesn't. I've also tried using -[UITableViewCell appearanceWhenContainedIn:(Class)]
, and that doesn't work either.
Any ideas?
Update (2013/7/8) - This has been fixed in newer versions of iOS. However, it's worth knowing about if you're targeting iOS 6 or below.
You can blame Apple for this one, and it's actually pretty mean of them. Technically, backgroundColor
is not customizable through appearance proxies.
From Apple's documentation:
To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.
If we go into a class like UIBarButtonItem
and look at the tintColor
property we see this:
@property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;
So because it's marked with the UI_APPEARANCE_SELECTOR
tag we know it works with UIAppearance
.
Here's where Apple are particularly mean: in a UIView
, backgroundColor
has no appearance selector tag, but still works with UIAppearance
. According to all the documentation Apple provide it should not, but yet it does!
This gives the misleading impression that it will work for all sub-classes of UIView
, including UITableView
. This has come up before, in this previous SO answer
So the bottom line is that backgroundColor
shouldn't work at all with UIAppearance
, but for some reason it does on a UIView
. It is not guaranteed to work on UIView
subclasses, and it doesn't work at all on UITableView
. Sorry I couldn't give you a more positive answer!
You can create your own subclass of UITableViewCell that conforms to UIAppearance and mark a custom setter with UI_APPEARANCE_SELECTOR. Then set the cell backgroundColor on the superlass from your custom setter .
In your appDelegate
[[CustomCell appearance] setBackgroundCellColor:[UIColor redColor]];
In your UItableView subclass
@interface CustomCell : UITableViewCell <UIAppearance>
@property (nonatomic, weak) UIColor *backgroundCellColor UI_APPEARANCE_SELECTOR;
@implementation CustomCell
@synthesize backgroundCellColor;
-(void)setBackgroundCellColor:(UIColor *)backgroundColor
{
[super setBackgroundColor:backgroundColor];
}
I'm using ARC in this example.
Without Subclassing! Doing this on a subclass is probably NOT the best practice, especially if you want to hit all tableView backgrounds. That's a lot of subclassing. A lot of potential bugs. A mess really. The best way to do this is to use a category. You will have to set one up for both the tableViewCell and the tableView. I will just demonstrate the one for the cell. The property on the tableView you must do is the backgroundColor property. NB. I'm prepending my methods with "sat".
// .h
#import <UIKit/UIKit.h>
@interface UITableViewCell (Appearance)<UIAppearance>
@property (strong, nonatomic) UIColor *satBackgroundColor UI_APPEARANCE_SELECTOR;
@end
// .m
#import "UITableViewCell+Appearance.h"
@implementation UITableViewCell (Appearance)
- (UIColor *)satBackgroundColor
{
return self.backgroundColor;
}
- (void)setSatBackgroundColor:(UIColor *)satBackgroundColor
{
self.backgroundColor = satBackgroundColor;
}
@end
Now in your appDelegate or some manager class you'll import the category and just call it as if it had an appearance proxy built in.
UITableViewCell *cell = [UITableViewCell appearance];
cell.satBackgroundColor = [UIColor orangeColor];
Ok, so now just do the one for the tableView's background property. Simple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With