NSAttributedString
is a Foundation class used for more complicated string styling within iOS. You can change things like color, font, size, kerning, etc on specific ranges within a string using NSAttributedString
. Attributes for an NSAttributedString
are set using a dictionary, and the iOS SDK provides a number of keys you can use for that dictionary such as NSAttributedString.Key.foregroundColor
.
NSAttributedString
allows you to customize the text attributes of UILabel, UIButton, UIPickerView, and UITableViewCell.
Let’s look at a simple example
let attributes: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.blue] let attributedString = NSAttributedString(string: "Swift here", attributes: attributes) myLabel.attributedText = attributedString
Here we’re creating our attributes dictionary with a foreground color of blue, then creating an attributed string with those attributes. Finally, we’re setting the text on a UILabel to the new attributed string.
Say we want the word "Swift" to be one font, and the word "here" to be a different font.
let swiftAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 16)] let hereAttributes: [NSAttributedString.Key: Any] = [.font: UIFont(name: "Avenir-Light", size: 14.0)] let swiftString = NSMutableAttributedString(string: "Swift", attributes: helloAttributes) let hereString = NSAttributedString(string: "here", attributes: worldAttributes) swiftString.append(hereString) myLabel.attributedText = swiftString
If you’ve ever worked with NSRange before then you can simplify what’s happening above a little bit like this:
let swiftAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-Bold", size: 20.0)] let hereAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont(name: "Avenir-Light", size: 14.0)] let str = NSMutableAttributedString(string: "Swift here", attributes: swiftAttributes) str.addAttributes(hereAttributes, range: NSRange(location: 6, length: 4)) myLabel.attributedText = str
Ranges can be really helpful when you’re manipulating a string.
let swiftString = "Swift is the best language ever!" let boldAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-Bold", size: 20.0)] let range = NSString(string: swiftString).range(of: "best") let swiftAttributedString = NSMutableAttributedString(string: swiftString) swiftAttributedString.addAttributes(boldAttributes, range: range) myLabel.attributedText = swiftAttributedString
There are lots of formatting options for attributed strings, including:
.underlineStyle
to a value from NSUnderlineStyle
to strike out characters..strikethroughStyle
to a value from NSUnderlineStyle
to strike out characters..paragraphStyle
to an instance of NSMutableParagraphStyle
to control text alignment and spacing..link
to be a URL to make clickable links in your strings.Now lets apply different color to some characters by adding another attribute just after the first addAttribute
line
let string = "https://en.proft.me" let attributedString = NSMutableAttributedString(string: string) attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blue, range: NSRange(location: 7, length: 11))
Add another attribute to the attributed string just after the last addAttribute
line
attributedString.addAttribute(NSStrokeColorAttributeName, value: UIColor.red, range: NSRange(location: 7, length: 11))
Make some characters bold using NSAttributedString
attributedString.addAttribute(NSFontAttributeName, value: UIFont(name: "AmericanTypewriter-Bold", size: 24)!, range: NSRange(location: 7, length: 11))
We can use NSUnderlineColorAttributeName
and NSUnderlineStyleAttributeName
to define underline color and style for our string
attributedString.addAttribute(NSUnderlineColorAttributeName, value: UIColor.blue, range: NSRange(location: 0, length: 18)) attributedString.addAttribute(NSUnderlineStyleAttributeName, value: 1, range: NSRange(location: 0, length: 18))
HTML as NSAttributedString
Converting HTML String to NSAttributedString
can be easily accomplished with this String extension:
extension String { func htmlAttributedString() -> NSAttributedString? { guard let data = self.data(using: .utf8) else { return nil } return try? NSAttributedString( data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil ) } }
To use,
label.attributedText = "<b>Hello</b> \u{2022} World".htmlAttributedString()
Justify Text
let sampleText = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." // Create label let label = UILabel(frame: CGRectMake(0, 0, view.frame.size.width, 400)) label.numberOfLines = 0 label.lineBreakMode = NSLineBreakMode.ByWordWrapping // Justify text through paragraph style let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = NSTextAlignment.Justified let attributes = [NSParagraphStyleAttributeName: paragraphStyle, NSBaselineOffsetAttributeName: NSNumber(float: 0)] let attributedString = NSAttributedString(string: sampleText, attributes: attributes) label.attributedText = attributedString view.addSubview(label)
Custom kerning (letter spacing)
var attributedString = NSMutableAttributedString("Apply kerning") attributedString.addAttribute(attribute: NSKernAttributeName, value: 5, range: NSMakeRange(6, 7)) label.attributedText = attributedString
Line and paragraph spacing
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineHeightMultiple = 1.5 let attributes = [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body), NSAttributedString.Key.paragraphStyle: paragraphStyle, NSAttributedString.Key.foregroundColor: UIColor.label ] textView.attributedText = NSAttributedString(string: sampleText, attributes: attributes)
Useful links