Attributed String for iOS in Swift
An iOS SDK Tutorial
I have been talking quite a lot in the past about how to customize text in your app to improve the UI of your applications. Before iOS 6, Core Text was the only available option for developers. Although a great framework, Core Text is not a very straightforward tool to use. You can check our Core Text tutorial in Objective-C here. In iOS 6, Apple introduced NSAttributedString. You can check a couple of posts about this topic here and here.
Core Text still remains the way to go for some specific cases that we will see later but NSAttributedString brings less hassle so, if possible, you should adopt it as a your first option. Then, on early June 2014, Apple introduced Swift. In this tutorial, we will build a project using Swift and NSAttributedString.
First, let me tell you more about some Cocoa classes that give you easy access to text customization. NSAttributedString allows you to customize the text attributes of UILabel, UIButton, UIPickerView, and UITableViewCell.
To use these properties, you just have to add any object of type UILabel, UIButton, UIPickerView or UITableViewCell to your project and assign an NSAttributedString. For example, for a UILabel object, you would do the following:
self.labelName.attributedText = attributedString
Let’s build an example
Let’s write some code to see how to create attributed strings using Swift.
Launch Xcode and create a new Single-View Application project. Name it AttributedStringExample. Open the ViewController.swift file and edit the viewDidLoad() method as follows:
override func viewDidLoad() {
super.viewDidLoad()
if let titleFont = UIFont(name: "Copperplate", size: 50.0) {
let shadow : NSShadow = NSShadow() shadow.shadowOffset = CGSizeMake(-2.0, -2.0) let attributes = [
NSFontAttributeName : titleFont,
NSUnderlineStyleAttributeName : 1,
NSForegroundColorAttributeName : UIColor.whiteColor(),
NSTextEffectAttributeName : NSTextEffectLetterpressStyle,
NSStrokeWidthAttributeName : 3.0,
NSShadowAttributeName : shadow] var title = NSAttributedString(string: "NSAttributedString", attributes: attributes) //1 var label = UILabel(frame: CGRectMake(((self.view.bounds.size.width - title.size().width) / 2.0), 40.0, title.size().width, title.size().height)) //2
label.attributedText = title //3
view.addSubview(label) //4
}
}
Here, we create the attributed string with the attributes in Line 1. In this particular case, we set the font and the size, text effect, color, shadow and underline attribute.
Line 2 instantiates a label and Line 3 sets the attributed string to the label. Finally (Line 4), we add the label as a subview of the viewcontroller view. I also changed to blue the background color of the view from the attributes Inspector in Interface Builder. Now, just build and run and you should see the following result:
This example shows how to create an attributed string and how to assign it to the attributedText property from a UILabel. Easy, right? But you may wonder, which attributes can I apply? Let’s check them out, one by one.
Character Attributes
Let’s check the character attributes currently available that you can apply to your text:
NSFontAttributeName
This allows you to change the font of your text. If not specified otherwise, default is 12-point Helvetica(Neue).
NSParagraphStyleAttributeName
This allows you to apply multiple attributes (such as alignment, tab stops and line break mode) to a range of text (aka paragraph).
NSForegroundColorAttributeName
The color of the text during rendering (black, by default). The image below shows an example with red foreground.
NSBackgroundColorAttributeName
The color of the background area behind the text (no color, by default). Here, an example with yellow background in the image below.
NSLigatureAttributeName
Ligatures cause specific character combinations to be rendered using a single custom glyph that corresponds to those characters. The default value is 1, indicating the use of ligatures. You can specify no ligatures with value 0. The following image shows the difference between setting a text with ligature attribute 0 (top text) and 1 (bottom text). Pay attention to the ff in caffeteria, the ffi in ufficiale and the ffl in affluente. They all belong to the f-ligatures type and they solve the unatractive collision between elements of the neighboring characters (the hook and crossbar of a double f or the hook of the f and the dot of the i).
NSKernAttributeName
Kern specifies the space between specific characters and it’s font-dependent. The default value is 0, which means no kerning. Any other number will specify the number of points between characters.
The following image shows the difference between setting a text with kern attribute value 10 (top text) and 0(bottom text).
NSStrikethroughStyleAttributeName
The value of this attribute indicates wether the text is crossed out (strikethrough). Default value is none but you can specify several values to cross out the text with different styles. The following example shows the result of applying different values of this property.
NSUnderlineStyleAttributeName
The value of this attribute indicates wether the text is rendered with a line under. The default value is none, but you can specify different values of underlining matching the same styles as for the strikethrough style.
NSStrokeColorAttributeName
This UIColor describes the outline color of the text. The default value is the same UIColor defined as the text foreground.
NSStrokeWidthAttributeName
This value represent the amount to change the stroke width. By default is 0, for no additional changes. A positive value will change the stroke width alone, a negative value will stroke and fill the text.
Find an example in the image below.
NSShadowAttributeName
This attribute allows you to add shadow to your text. Default value is nil, which mean, no shadow. Find an example in the image below.
NSTextEffectAttributeName
Use this attribute to specify a text effect. By default the value of this property is nil, indicating no text effect.
NSAttachmentAttributeName
The value of this attribute is an NSTextAttachment object. The default value of this property is nil, indicating no attachment.
NSLinkAttributeName
The value of this attribute is an NSURL or and NSString object. The default value of this property is nil, indicating no link.
NSBaselineOffsetAttributeName
This attribute indicates the character’s offset from the baseline, expressed in points. The baseline is the imaginary line upon which a line of text rests. The default value is 0. The baseline for the text below is the red line.
NSUnderlineColorAttributeName
This attribute indicates the color of the line underneath the text. The default value coincides with the foreground color. Find an example with a green double line in the image below.
NSStrikethroughColorAttributeName
This attribute indicates the color of the cross out line. The default value is the same as the foreground color. Find an example with a red line in the image below.
NSObliquenessAttributeName
This attribute indicates the skew to be applied to glyphs. The default value is 0, meaning no skew. A positive value will lean the text towards the right, a negative value will lean it towards the left. This attribute allows you to create your own italic version for a typeface that doesn’t have one. However, before you create your own, think if there might be a reason why the font doesn’t have the oblique version. Find an example using ‘Academy Engraved LET’ using a skew value of 1.
NSExpansionAttributeName
This attribute indicates the log of the expansion factor to be applied to glyphs. Default value is 0, no expansion. Use a positive value to enlarge and a negative value to shrink the text. The following image shows the difference between setting a text with expansion factor 0 (text at the top) and 1 (text at the bottom).
NSWritingDirectionAttributeName
This attribute can help you write text from Left-to-Right and from Right-to-Left. You can also embed text in a text with a different writing direction and override the inherent directionality of characters.
NSVerticalGlyphFormAttributeName
This attribute indicates with value 0 horizontal text and with value 1 vertical text. In iOS, horizontal text is always used and specifying a different value is undefined. That means that you should not be using this attribute in iOS.
These are all the attributes offered by Apple that you can apply to the text in your apps. You can add or remove attributes to a particular range of characters using NSMutableAttributedString combining chunks of text with different attributes. Here an example combining different styles:
NSAttributedString limitations
There are a couple of things that I’m aware of that are still not possible to do with attributed strings:
- If you need to render text vertically, attributed strings don’t seem to offer this solution just yet.
- If you want to draw into a shape other than a rectangle, you will still have to use Core Text.
- If you want to render your text on a non-horizontal line (such as a curved line), you will probably have to pick either Core Text or a CATextLayer.
However, Apple is adding more and more attributes to make it easier for us to render text and I’m happy to share with you all those improvements. I hope you found this post useful!
Happy coding!
Eva
Eva Diaz-Santana (@evdiasan) is cofounder of InvasiveCode. She develops iOS applications and teaches iOS development since 2008. She worked at Apple as Cocoa Architect and UX designer.