1.26. Constructing and Displaying Styled Texts

Problem

You want to be able to display rich formatted text in your UI components without having to create a separate UI component per attribute. For instance, you may want to display one sentence that contains only one of its words written in bold, inside a UILabel.

Solution

Construct an instance of the NSAttributedString or the mutable variant of it, the NSMutableAttributedString, and either set it as the text of a UI component like the UILabel component through its special attributed string property, or simply use the attributed string’s built-in methods to draw the text on a canvas.

Discussion

Rich text is a thing of legend! A lot of us programmers have had the requirement to display mixed-style strings in one line of text on our UI. For instance, in one line of text you may have to display straight and italic text together, where one word is italic and the rest of the words are regular text. Or you may have had to underline a word inside a sentence. For this, some of us had to use Web Views, but that is not the optimal solution because Web Views are quite slow in rendering their content, and that will definitely impact the performance of your app. In iOS 7, we can start using attributed strings. I don’t know what took Apple so long to introduce this feature to iOS, as Mac developers have been using attributed strings for a long time now!

Before we begin, I want to clearly show you what I mean by attributed strings, using Figure 1-69. Then we will set out on the journey to write the program to achieve exactly this.

An attributed string is displayed on the screen inside a simple label

Figure 1-69. An attributed string is displayed on the screen inside a simple label

Note

Just to be explicit, this text is rendered inside a single instance of the UILabel class.

So what do we see in this example? I’ll list the pieces:

The text “iOS” with the following attributes:
  • Bold font with size of 60 points

  • Background color of black

  • Font color of red

The text “SDK” with the following attributes:
  • Bold font with size of 60 points

  • White text color

  • Light-gray shadow

  • Red background color

The best way to construct attributed strings is to use the initWithString: method of the mutable variant of the NSMutableAttributedString class and pass an instance of the NSString to this method. This will create our attributed string without any attributes. Then, to assign attributes to different parts of the string, we will use the setAttributes:range: method of the NSMutableAttributedString class. This method takes in two parameters:

setAttributes

A dictionary whose keys are character attributes and the value of each key depends on the key itself. Here are the most important keys that you can set in this dictionary:

NSFontAttributeName

The value of this key is an instance of UIFont and defines the font for the specific range of your string.

NSForegroundColorAttributeName

The value for this key is of type UIColor and defines the color for your text for the specific range of your string.

NSBackgroundColorAttributeName

The value of this key is of type UIColor and defines the background color on which the specific range of your string has to be drawn.

NSShadowAttributeName

The value of this key must be an instance of the NSShadow and defines the shadow that you want to use under the specific range of your string.

range

A value of type NSRange that defines the starting point and the length of characters to which you want to apply the attributes.

Note

To see all the different keys that you can pass to this method, simply browse the Apple documentation online for the NSMutableAttributedString class. I will not put the direct URL to this documentation here as Apple may change the URL at some point, but a simple search online will do the trick.

We’ll break our example down into two dictionaries of attributes. The dictionary of attributes for the word “iOS” can be constructed in this way in code:

NSDictionary *attributesForFirstWord = @{
                 NSFontAttributeName : [UIFont boldSystemFontOfSize:60.0f],
                 NSForegroundColorAttributeName : [UIColor redColor],
                 NSBackgroundColorAttributeName : [UIColor blackColor]
                 };

And the word “SDK” will be constructed using the following attributes:

NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor darkGrayColor];
shadow.shadowOffset = CGSizeMake(4.0f, 4.0f);

NSDictionary *attributesForSecondWord = @{
                  NSFontAttributeName : [UIFont boldSystemFontOfSize:60.0f],
                  NSForegroundColorAttributeName : [UIColor whiteColor],
                  NSBackgroundColorAttributeName : [UIColor redColor],
                  NSShadowAttributeName : shadow
                  };

Putting it together, we will get the following code that not only creates our label, but also sets its attributed text:

#import "ViewController.h"

@interface ViewController ()
@property (nonatomic, strong) UILabel *label;
@end

@implementation ViewController

- (NSAttributedString *) attributedText{

    NSString *string = @"iOS SDK";

    NSMutableAttributedString *result = [[NSMutableAttributedString alloc]
                                         initWithString:string];

    NSDictionary *attributesForFirstWord = @{
                     NSFontAttributeName : [UIFont boldSystemFontOfSize:60.0f],
                     NSForegroundColorAttributeName : [UIColor redColor],
                     NSBackgroundColorAttributeName : [UIColor blackColor]
                     };

    NSShadow *shadow = [[NSShadow alloc] init];
    shadow.shadowColor = [UIColor darkGrayColor];
    shadow.shadowOffset = CGSizeMake(4.0f, 4.0f);

    NSDictionary *attributesForSecondWord = @{
                      NSFontAttributeName : [UIFont boldSystemFontOfSize:60.0f],
                      NSForegroundColorAttributeName : [UIColor whiteColor],
                      NSBackgroundColorAttributeName : [UIColor redColor],
                      NSShadowAttributeName : shadow
                      };

    /* Find the string "iOS" in the whole string and sets its attribute */
    [result setAttributes:attributesForFirstWord
                    range:[string rangeOfString:@"iOS"]];

    /* Do the same thing for the string "SDK" */
    [result setAttributes:attributesForSecondWord
                    range:[string rangeOfString:@"SDK"]];

    return [[NSAttributedString alloc] initWithAttributedString:result];

}

- (void)viewDidLoad{
    [super viewDidLoad];

    self.label = [[UILabel alloc] init];
    self.label.backgroundColor = [UIColor clearColor];
    self.label.attributedText = [self attributedText];
    [self.label sizeToFit];
    self.label.center = self.view.center;
    [self.view addSubview:self.label];

}

@end

Get iOS 7 Programming Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.