Logo

iNVASIVECODE - Blog

  • Archive
  • RSS
  • Ask us anything about iOS
banner
Introduction to NSAttributedString for iOS 6

I’ve been talking a lot in the past about how to customize text in your app to improve the UI of your applications. You need to show some text in a particular way or with some characteristics that are not standard and until now, you just were not able to accomplish that with simple methods and everyday-frameworks.

Before iOS 6, developers had to turn out to Core Text, which although a great framework is not easy to use. You can check the Core Text tutorial here and how much code you needed to implement to do things that I consider were fairly basic. Finally, Apple gave us what we were looking for and gratefully improved NSAttributedString in iOS 6. And I personally think that the most important thing that Apple has done is that it has put together some documentation, which still lacks for Core Text. Core Text still remains as a useful API to do some particular things like writing inside non-rectangular shapes, for example, but let’s see the new features of NSAttributedString.

Although NSAttributedString was with us since iOS 5, it was limited to few attributes. Now, not only new string attributes were added, but NSAttributedString is more pervasive in iOS and you can feed: UILabel, UIButton, UIPickerView, and UITableViewCell.

UILabel

For the UILabel, you can use the following property

@property (nonatomic,copy) NSAttributedString *attributedText


UIButton

For the class UIButton, you can instead use the following method:

- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state


UIPickerView and UITableViewCell

You can fill the last two classes (UIPickerView and UITableViewCell) through their property:

@property(nonatomic, readonly, strong) UILabel *textLabel


assigning an attributed string to this label.

Let’s go

Let’s write some code to see how easy it is to implement what we’ve been talking about so far.

Launch Xcode and create a new Single-View Application iPad project. Name it AttributedString. Open the ViewController.m and edit the -viewDidLoad method as follows:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSAttributedString *title;
    title = [[NSAttributedString alloc] initWithString:@"Visual Guide for NSAttributedString" attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Noteworthy-Bold" size:36], NSUnderlineStyleAttributeName : @1 , NSStrokeColorAttributeName : [UIColor blackColor]}]; //1
    UILabel *label;
    label = [[UILabel alloc] initWithFrame:CGRectMake( (self.view.bounds.size.width - title.size.width) / 2.0f, 40.0f, title.size.width, title.size.height)]; //2
    label.attributedText = title; //3
    [self.view addSubview:label]; //4
}


Line 1 creates an attributed string with a set of attributes. In this particular case, we set the font, the font size, the stroke color and underline attribute. Check the documentation (“) if you want to apply additional customizations, but for a quick reference I’m going to list them here (I think the name of the attribute is self explanatory):

NSString *const NSFontAttributeName;
NSString *const NSParagraphStyleAttributeName;
NSString *const NSForegroundColorAttributeName;
NSString *const NSBackgroundColorAttributeName; 
NSString *const NSLigatureAttributeName;
NSString *const NSBaselineOffsetAttributeName;
NSString *const NSStrikethroughStyleAttributeName;
NSString *const NSStrokeColorAttributeName; 
NSString *const NSStrokeWidthAttributeName;
NSString *const NSShadowAttributeName;


Line 2 creates a label and Line 3 applies the attributed string to the label. Finally (Line 4), we add our label as a subview to our view. Now, just build and run and you should see the following result:



Note that you can also add or remove attributes to a particular range of characters using NSMutableAttributedString. See the class description for NSMutableAttributedString for more information about the available methods.

Drawing made easier

There are also a couple of new categories that have been introduced with iOS 6. A basic category:

#import 
@interface NSAttributesString (NSStringDrawing)
- (CGSize)size;
- (void)drawAtPoint:(CGPoint)point;
- (void)drawInRect:(CGRect)rect;
@end


and a more sophisticated category:

@interface NSAttributesString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect 
        options:(NSStringDrawingOptions *)options 
        context:(NSStringDrawingContext *)context;
- (CGRect)boundingRectWithSize:(CGSize)size 
        options:(NSStringDrawingOptions *)options 
        context:(NSStringDrawingContext *)context;
@end


Let’s see how all of this works and let’s continue with our project. Create a new Objective-C class, subclass of UIView, and name it TextRenderingView. Create a NSAttributedString property and name it theString. Then, in the TextRenderingView.m edit the drawRect: method as follows:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    [theString drawInRect:CGRectMake((self.bounds.size.width - theString.size.width) / 2.0f, 40.0f, theString.size.width, theString.size.height)];
}


Here, we call the drawRect: on the super class to let it do all the setups. Then, we just use a method from the NSStringDrawing category:

- (void)drawInRect:(CGRect)rect;


Go back to the ViewController.m and import the TextRenderingView header:

#import "TextRenderingView.h"


Modify the viewDidLoad as follows:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSAttributedString *title;
    title = [[NSAttributedString alloc] initWithString:@"Visual Guide for NSAttributedString" attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Noteworthy-Bold" size:36], NSUnderlineStyleAttributeName : @1 , NSStrokeColorAttributeName : [UIColor blackColor]}]; //1

    TextRenderingView *textView; 
    textView = [[TextRenderingView alloc] initWithFrame:self.view.frame]; //5
    self.view = textView; //6
    textView.backgroundColor = [UIColor whiteColor]; //7
    textView.theString = title; //8
}


Line 1 creates the attributed string in the same way we did before. Now, we initialize our TextRenderingView (Line 5) and set it as the view of ViewController (Line 6). We set the background color to white (Line 7) and finally, we pass the created attributed string to the rendering view (Line 8). Now, just Run and if you did not make any mistake, you should see the same result as before.

I’m sure that if you followed the last tutorial regarding Core Text or even if you tried by yourself in the past, you will agree with me that it has become really simpler to render text in the way we want it to be. I think Apple has put a lot of effort and we should take advantage to improve our apps. I challenge you to add some creativity to the projects we’ve been working on and experiment with the different possibilities that NSAttributedString is offering us. It should be fairly easy now to build something like this:



The limits of NSAttributedString

There are a couple of things that I’m aware of that are not possible to do with those new methods and categories:

if you want to draw into a shape different from a rectangle, you will still have to use Core Text.
if you want to render your text on a non-horizontal line, you will probably have to pick either Core Text or CALayer.
See the next figure as an example of what can not be done with NSAttributedString:



Other than that, again, I think there is a lot of potential and I’m happy to share with you all those improvements regarding text rendering. I hope you found this post useful!

Enjoy!

Eva

Eva Diaz-Santana is co-founder of iNVASIVECODE. She is senior iOS developer and works mainly on location-based services, text and graphics processing, and core data.
Pop-upView Separately

Introduction to NSAttributedString for iOS 6

I’ve been talking a lot in the past about how to customize text in your app to improve the UI of your applications. You need to show some text in a particular way or with some characteristics that are not standard and until now, you just were not able to accomplish that with simple methods and everyday-frameworks. Before iOS 6, developers had to turn out to Core Text, which although a great framework is not easy to use. You can check the Core Text tutorial here and how much code you needed to implement to do things that I consider were fairly basic. Finally, Apple gave us what we were looking for and gratefully improved NSAttributedString in iOS 6. And I personally think that the most important thing that Apple has done is that it has put together some documentation, which still lacks for Core Text. Core Text still remains as a useful API to do some particular things like writing inside non-rectangular shapes, for example, but let’s see the new features of NSAttributedString.

Although NSAttributedString was with us since iOS 5, it was limited to few attributes. Now, not only new string attributes were added, but NSAttributedString is more pervasive in iOS and you can feed: UILabel, UIButton, UIPickerView, and UITableViewCell.

UILabel

For the UILabel, you can use the following property

@property (nonatomic,copy) NSAttributedString *attributedText

UIButton

For the class UIButton, you can instead use the following method:

- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state

UIPickerView and UITableViewCell

You can fill the last two classes (UIPickerView and UITableViewCell) through their property:

@property(nonatomic, readonly, strong) UILabel *textLabel

assigning an attributed string to this label.

Let’s go

Let’s write some code to see how easy it is to implement what we’ve been talking about so far.

Launch Xcode and create a new Single-View Application iPad project. Name it AttributedString. Open the ViewController.m and edit the -viewDidLoad method as follows:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSAttributedString *title;
    title = [[NSAttributedString alloc] initWithString:@"Visual Guide for NSAttributedString" attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Noteworthy-Bold" size:36], NSUnderlineStyleAttributeName : @1 , NSStrokeColorAttributeName : [UIColor blackColor]}]; //1
    UILabel *label;
    label = [[UILabel alloc] initWithFrame:CGRectMake( (self.view.bounds.size.width - title.size.width) / 2.0f, 40.0f, title.size.width, title.size.height)]; //2
    label.attributedText = title; //3
    [self.view addSubview:label]; //4
}

Line 1 creates an attributed string with a set of attributes. In this particular case, we set the font, the font size, the stroke color and underline attribute. Check the documentation (“) if you want to apply additional customizations, but for a quick reference I’m going to list them here (I think the name of the attribute is self explanatory):

NSString *const NSFontAttributeName;
NSString *const NSParagraphStyleAttributeName;
NSString *const NSForegroundColorAttributeName;
NSString *const NSBackgroundColorAttributeName; 
NSString *const NSLigatureAttributeName;
NSString *const NSBaselineOffsetAttributeName;
NSString *const NSStrikethroughStyleAttributeName;
NSString *const NSStrokeColorAttributeName; 
NSString *const NSStrokeWidthAttributeName;
NSString *const NSShadowAttributeName;

Line 2 creates a label and Line 3 applies the attributed string to the label. Finally (Line 4), we add our label as a subview to our view. Now, just build and run and you should see the following result:

alt text

Note that you can also add or remove attributes to a particular range of characters using NSMutableAttributedString. See the class description for NSMutableAttributedString for more information about the available methods.

Drawing made easier

There are also a couple of new categories that have been introduced with iOS 6. A basic category:

#import 
@interface NSAttributesString (NSStringDrawing)
- (CGSize)size;
- (void)drawAtPoint:(CGPoint)point;
- (void)drawInRect:(CGRect)rect;
@end

and a more sophisticated category:

@interface NSAttributesString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect 
        options:(NSStringDrawingOptions *)options 
        context:(NSStringDrawingContext *)context;
- (CGRect)boundingRectWithSize:(CGSize)size 
        options:(NSStringDrawingOptions *)options 
        context:(NSStringDrawingContext *)context;
@end

Let’s see how all of this works and let’s continue with our project. Create a new Objective-C class, subclass of UIView, and name it TextRenderingView. Create a NSAttributedString property and name it theString. Then, in the TextRenderingView.m edit the drawRect: method as follows:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    [theString drawInRect:CGRectMake((self.bounds.size.width - theString.size.width) / 2.0f, 40.0f, theString.size.width, theString.size.height)];
}

Here, we call the drawRect: on the super class to let it do all the setups. Then, we just use a method from the NSStringDrawing category:

- (void)drawInRect:(CGRect)rect;

Go back to the ViewController.m and import the TextRenderingView header:

#import "TextRenderingView.h"

Modify the viewDidLoad as follows:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSAttributedString *title;
    title = [[NSAttributedString alloc] initWithString:@"Visual Guide for NSAttributedString" attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Noteworthy-Bold" size:36], NSUnderlineStyleAttributeName : @1 , NSStrokeColorAttributeName : [UIColor blackColor]}]; //1

    TextRenderingView *textView; 
    textView = [[TextRenderingView alloc] initWithFrame:self.view.frame]; //5
    self.view = textView; //6
    textView.backgroundColor = [UIColor whiteColor]; //7
    textView.theString = title; //8
}

Line 1 creates the attributed string in the same way we did before. Now, we initialize our TextRenderingView (Line 5) and set it as the view of ViewController (Line 6). We set the background color to white (Line 7) and finally, we pass the created attributed string to the rendering view (Line 8). Now, just Run and if you did not make any mistake, you should see the same result as before.

I’m sure that if you followed the last tutorial regarding Core Text or even if you tried by yourself in the past, you will agree with me that it has become really simpler to render text in the way we want it to be. I think Apple has put a lot of effort and we should take advantage to improve our apps. I challenge you to add some creativity to the projects we’ve been working on and experiment with the different possibilities that NSAttributedString is offering us. It should be fairly easy now to build something like this:

alt text

The limits of NSAttributedString

There are a couple of things that I’m aware of that are not possible to do with those new methods and categories:

  1. if you want to draw into a shape different from a rectangle, you will still have to use Core Text.
  2. if you want to render your text on a non-horizontal line, you will probably have to pick either Core Text or CALayer.

See the next figure as an example of what can not be done with NSAttributedString:

alt text

Other than that, again, I think there is a lot of potential and I’m happy to share with you all those improvements regarding text rendering. I hope you found this post useful!

Enjoy!

Eva

Eva Diaz-Santana is co-founder of iNVASIVECODE. She is senior iOS developer and works mainly on location-based services, text and graphics processing, and core data.

    • #attributed string
    • #nsattributedstring
    • #ios 6
    • #uikit
    • #ios
    • #iphone
    • #ipad
    • #os x
    • #mountain lion
    • #Core Text
  • 8 months ago
  • 4
  • Permalink
  • Share
    Tweet

4 Notes/ Hide

  1. r-second likes this
  2. plasticdreams reblogged this from do-nothing
  3. do-nothing reblogged this from invasivecode
  4. bballentine likes this
  5. invasivecode posted this
← Previous • Next →
iNVASIVECODE is a design and development enterprise with the passion for engineering beautiful iOS and OS X apps.

iNVASIVECODE offers 5-days iOS training classes for professional developers and on-site technical consulting.

Pages

  • HOME
  • iOS TRAINING CLASSES
  • TUTORIAL ON CORE TEXT
  • QUARTZ CRASH COURSE
  • CONTACT US

More about us

  • @invasivecode on Twitter
  • Google
  • Linkedin Profile

loading tweets…

I Dig These Posts

See more →
  • RSS
  • Random
  • Archive
  • Ask us anything about iOS
  • Mobile

Copyright ©2008-2013 iNVASIVECODE, Inc. Effector Theme by Carlo Franco.

Powered by Tumblr