Objective-C Categories as Stylesheets

Xcode

It is very important that iPhone and iPad applications use visual styles in a coherent way. This helps users learn how to use your application faster, it helps them scan your UI for important information as quickly as possible, and it can also convey a strong marketing message; companies who want iPhone or iPad applications often have complex visual identities, including predefined fonts and colors, and they will want their applications to match those choices.

However, getting all the UI widgets to look similar can be complex, particularly in large applications; what if your client or their designers change their minds about the font size or some background color right before shipping your project? Of course you can “search and replace” all occurrences of some color using Xcode, but you run the risk of leaving some unchanged widget somewhere. And believe me, this happens really often.

In this article I discuss a simple approach, using Objective-C categories, to keep your styling information separated from the rest of the application, using a system that will be familiar to developers used to creating websites using CSS (Cascading Style Sheets).

FIRST APPROACH: SIMPLE CATEGORIES

The first, easiest approach is to create simple UIFont and UIColor categories in your application, and provide semantic descriptions of the data you want to style; for example customerNameFont and companyPhoneColor are good names. You can add as many class methods as you want to the UIFont and UIColor classes for that:

@interface UIFont (YourAppName)

+ (UIFont *)customerNameFont;
+ (UIFont *)customerPhoneFont;

@end

@implementation UIFont (YourAppName)

+ (UIFont *)customerNameFont
{
    return [UIFont fontWithName:@"Helvetica" size:22.0];
}

+ (UIFont *)customerPhoneFont
{
    return [UIFont boldSystemFontOfSize:15.0];
}

@end

And we provide the same treatment to the UIColor class:

@interface UIColor (YourAppName)

+ (UIColor *)customerNameColor;
+ (UIColor *)customerPhoneColor;

@end

@implementation UIColor (YourAppName)

+ (UIColor *)customerNameColor
{
    return [UIColor blueColor];
}

+ (UIColor *)customerPhoneColor
{
    return [UIColor redColor];
}
@end

Then, you can use those method names in the rest of your application:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                       reuseIdentifier:CellIdentifier] autorelease];

        // And here goes the styling!
        cell.textLabel.font = [UIFont customerNameFont];
        cell.textLabel.textColor = [UIColor customerNameColor];

        cell.detailTextLabel.font = [UIFont customerPhoneFont];
        cell.detailTextLabel.textColor = [UIColor customerPhoneColor];
    }

    Customer *cust = [self.data objectAtIndex:indexPath.row];
    cell.textLabel.text = cust.name;
    cell.detailTextLabel.text = cust.phone;

    return cell;
}

The advantage of this simple approach is that all styles are managed from a central location, and you can change the fonts and colors of your application in a single step.

There are, however, two major disadvantages:

  • Colors and fonts defined in their respective categories will not be available in Interface Builder, so you might have to override viewDidLoad or other methods to force the styling at a certain moment, or to set the color and font values manually, which might lead to duplicate information.
  • Some UI elements support even more styling information, like shadows or CGAffineTransform values, which cannot be handled in a simple way with this method.

We need some kind of CSS for iPhone applications, and the next section provides a rudimentary approach to that problem.

SECOND APPROACH, “CASCADING STYLE” CLASSES

Let’s push the idea of semantic styling a bit; in the previous example, we created separate categories for UIFont and UIColor and used them in atomic form, changing individual properties of your widgets, one by one.

What if you wanted to set several properties at once, just like with CSS classes on web pages? What if you had a system which could be extended to support more properties, for other, as of yet unknown, future UI widgets? For that, we would need a special container for style information, like a CSS stylesheet, and we should be able to assign this container to any kind of visual widget; in turn, those widgets would automatically adapt their layout and appearance. There are many different ways to do this; and this is just one of them.

First I declare a class called AKCascadingStyle, which holds basic styling information, and which is able to apply that information to any kind of object passed in as parameter:

@interface AKCascadingStyle : NSObject
{
@private
    UIFont *_font;
    UIColor *_textColor;
    UIColor *_backgroundColor;
    UIColor *_tintColor;
}

@property (nonatomic, retain) UIFont *font;
@property (nonatomic, retain) UIColor *textColor;
@property (nonatomic, retain) UIColor *backgroundColor;
@property (nonatomic, retain) UIColor *tintColor;

+ (id)style;
+ (id)styleFromObject:(id)object;

- (void)applyToObject:(id)object;
- (void)setValuesFromObject:(id)object;

@end

This class can be inherited and extended, and its methods can be overridden, as we’ll see shortly, to add support for more properties. Then I add a category on NSObject (careful with this!) to support adding and retrieving style information in the form of AKCascadingStyle instances:

@class AKCascadingStyle;

@interface NSObject (AKCascadingStyle)

@property (nonatomic, retain) AKCascadingStyle *cascadingStyle;

@end

Why a category on NSObject? Because not everything you see on your iPhone screen is a subclass of UIView! UIBarButtonItems, for example, inherit from UIBarItem, which itself inherits from NSObject, and not from UIView. By the way, by extending NSObject, this code could also be used in Mac OS X applications, for example, without modification.

Given that categories cannot add ivars to existing classes, the getter of this property will call the styleFromObject: method above:

@implementation NSObject (AKCascadingStyle)

@dynamic cascadingStyle;

- (void)setCascadingStyle:(AKCascadingStyle *)style
{
    [style applyToObject:self];
}

- (id)cascadingStyle
{
    return [AKCascadingStyle styleFromObject:self];
}

@end

Both applyToObject: and styleFromObject: are polymorphic (as all Objective-C methods are) so subclasses can extend their functionality as required (but don’t forget to send the same message to “super” before!):

@interface ShadowStyle : AKCascadingStyle
{
@private
    CGSize _shadowOffset;
    UIColor *_shadowColor;
}

@property (nonatomic) CGSize shadowOffset;
@property (nonatomic, retain) UIColor *shadowColor;

@end

Then, to use these style classes in your own controllers, just do the following:

- (IBAction)addStyle:(id)sender
{
    self.contentsTextView.cascadingStyle = [ShadowStyle style];
}

Setting this property will automatically set all the required parameters in your widget; text color, background colors, transformations, you name it. You can inherit styles in order to reuse them, and you can style pretty much any kind of UIKit widget with it.

You can download the code of this project from GitHub. The repository has been archived since 2010 (unchanged since its last push in June 2010), but it remains browsable, and the code still illustrates the technique well.

2026 UPDATE: WHERE THIS IDEA WENT

Reading this in 2026, the interesting part is not the code (manual reference counting, autorelease and retain are long gone in the ARC era) but the idea: central, semantic, reusable styling. Apple effectively agreed with it a year later, shipping UIAppearance in iOS 5 (2011), which lets you style entire classes of UIKit widgets from one place — with the same limitations this article predicted: not every property is proxyable, and there is no “cascading” or specificity resolution like real CSS.

The deeper answer arrived in 2019 with SwiftUI: declarative views with modifier chains, environment-driven values, and reusable “style” types (ButtonStyle, LabelStyle, etc.) are, in spirit, exactly the “CSS for mobile” this post was reaching for. The pattern worth keeping from 2010 is the one from the first approach: name your styles after what they mean (customerNameFont), never after what they look like (blueColor14). That advice has outlived UIKit, and it transfers 1:1 to design tokens in any framework today.

Leave a Reply

Your email address will not be published. Required fields are marked *