Our competences at your disposal on our blog
We love our job and we are glad to share it with you! Keep yourself fully informed about news and technologies we use to develop and which you may need! Follow our blog.
alex.reggiani's picture

In my previous post I've analyzed a simple solution that permits to create and use different themes for an application. This could be useful for those who are used to develop the user interface only by code.

For those who prefer to use the Interface Builder in order to create views, the technique showed earlier can’t be used. That is because all the images name, fonts and all the remaining attributes which establish the interface, are codified inside xib files, so they are not set up by code.

Personally, I prefer to create views by using Interface Builder because it allows me to design graphic interfaces using a graphic tool. This tool has the advantage of saving you from using tens and tens of code lines and, besides, it allows you to have an immediate visual feedback of how the created page will be.

There are different techniques that make an application themeable, even if it is developed by Interface Builder.
Besides the approach by code, we start creating a theme plist file which will contain all the resources that form the theme. At this point, we can choose between different alternatives.

1) It is possible to duplicate a view’s xib, a copy for every theme, allocating a different name for each copy. Then we implement the nibName method of our view controllers in order to make the appropriate xib coming back to the current theme.
For example, let’s assume that we have a ViewController called HomePageViewController and two themes, a default theme and a “dark” one, therefore we can perform two different HomePages, one for each theme.
The files we need to perform are the following:

schermata_2013-07-09_alle_23.56.21.png
schermata_2013-07-09_alle_23.57.28.png

In which default.plist contains:
schermata_2013-07-09_alle_23.59.06.png

and dark.plist :
schermata_2013-07-09_alle_23.59.49.png

Consecutively, we implement the HomePageViewController:

//
//  HomePageViewController.m
//
//  Created by Alex Reggiani on 09/07/13.
//  Copyright (c) 2013 Alex Reggiani. All rights reserved.
//

#import "HomePageViewController.h"

@implementation HomePageViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    
}

- (NSString *)nibName
{
    NSDictionary *theme = [ThemeManager sharedInstance].theme;
    return [theme objectForKey:NSStringFromClass([self class])];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

This technique, although it is really simple, needs to maintain several copies for the same xib, which implicates to generate over and over the same changes on N xib. In case it is necessary to add/remove/modify the components (i.e. a label) over the same xib.

2) Another technique (probably one of the most used, but not the best one) consists in performing as much IBOutlets as the components inside the xib, and then set the related images, font, colours into the viewcontroller’s viewDidLoad method.
This is certainly a very lumbering approach, but at least it doesn’t need to maintain duplicate xib of the same view.

3)The last technique, the one i personally prefer and the most effective, is that of creating subclasses of the components we want to thematize. Considering the labels, we can create a label subclass called, for example, ThemeLabel which will be responsible for setting up automatically the font and the colour during the moment in which it is instantiated.
Later, we use this ThemeLabel directly in the Interface Builder. Indeed, we add to our view a UILabel, we open the label’s tab “Identity Inspector” and we substitute the default class with a ThemeLabel.

schermata_2013-07-10_alle_00.16.20.png

Interface Builder allows you to use the so-called “User Defined Runtime Attributes” in order to specify which font has to be used for a given label. If we add two properties to the ThemeLabel (fontName and fontSize):

@interface ThemeLabel : UILabel
@property (nonatomic, copy) NSString *fontName;
@property (nonatomic, copy) NSString *fontSize;
@end

It will be enough to set up these two features into the Identity Inspector:
schermata_2013-07-10_alle_00.26.51.png

and read them into the ThemeLabel’s awakeFromNib method, so that you will be able to employ them.

I consider this technique the best of all for two main reasons:
- It prevents you from using such a lot of code lines
- It allows Runtime to modify the application’s theme. Indeed, it will be possible to introduce a mechanism by which ThemeManager, every time the user changes the theme, send a notification to all the ThemeLabels so that they will reshape the suitable theme.

At this point, the choice is yours!

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Type the characters you see in this picture. (verify using audio)

Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.