Attributed Text is an iOS SDK mechanism, represented by the NSAttributedString and NSMutableAttributedString classes, which allows applying multiple styles to different parts of a single text string. Unlike a regular NSString, Attributed String stores not only characters but also a dictionary of attributes for each range: font, color, line spacing, shadow, and alignment. According to Apple Developer Documentation, Attributed String is the foundation for displaying formatted text in UILabel, UITextView, and UITextField. It is the standard way to style text without WebKit or third-party libraries.
Key Takeaways
NSAttributedString is a Foundation framework class that represents a string with a set of named attributes bound to character ranges. Each attribute is a key-value pair: the key is defined by a constant (NSFontAttributeName, NSForegroundColorAttributeName), and the value is the corresponding object (UIFont, UIColor). Attributes are applied to a character range via NSRange.
The class is available on all Apple platforms: iOS (2.0+), macOS, tvOS, watchOS. NSAttributedString is immutable — once created, its attributes are fixed. For dynamic changes, NSMutableAttributedString is used, which inherits from NSAttributedString and adds methods setAttributes, addAttributes, addAttribute, removeAttribute.
NSString is a simple string of characters without styling information. Any text passed to UILabel via text is displayed with a single font, color, and size. NSAttributedString, passed via attributedText, allows each character to have its own set of attributes. UILabel, UITextView, and UITextField automatically recognize NSAttributedString and render the text according to its attributes.
Internally, NSAttributedString stores an NSString with the text and an array of attribute ranges. Each range is represented by an NSRange structure and an attribute dictionary. During rendering, the system iterates through the ranges and applies the corresponding attributes to each section. Efficiency depends on the number of attribute switches — frequent changes over short sections increase rendering time.
NSAttributedString attributes are constants defined in UIKit (iOS) and AppKit (macOS), each corresponding to a specific aspect of text visual styling. All attributes are NSAttributedString.Key strings, and their values are objects of specific classes. Attributes are divided into character-level (affecting characters) and paragraph-level (affecting paragraphs).
Character-level attributes include font (NSFontAttributeName), text color (NSForegroundColorAttributeName), background color (NSBackgroundColorAttributeName), underline (NSUnderlineStyleAttributeName), strikethrough (NSStrikethroughStyleAttributeName), shadow (NSShadowAttributeName). Paragraph-level attributes are set via NSParagraphStyleAttributeName, which controls alignment, indentation, line spacing, and tabulation.
NSLinkAttributeName creates a clickable link in the text: the value is a URL or string. UITextView automatically handles such links if interaction is enabled. NSAttachmentAttributeName allows embedding an NSTextAttachment — an image inside the text that renders as an inline element. This is used to create text with icons, emojis, or custom views within a string.
Each NSAttributedString attribute has a strictly typed value. Let’s look at the most commonly used attributes in iOS development. Font is set via a UIFont object, color via UIColor, line spacing via NSMutableParagraphStyle, which allows configuring alignment, indentation, and spacing in a single object.
| Attribute Key | Value Type | Purpose |
|---|---|---|
| NSFontAttributeName | UIFont | Text font |
| NSForegroundColorAttributeName | UIColor | Text color |
| NSBackgroundColorAttributeName | UIColor | Background color behind text |
| NSUnderlineStyleAttributeName | NSNumber (Int) | Underline style |
| NSParagraphStyleAttributeName | NSParagraphStyle | Paragraph settings |
| NSKernAttributeName | NSNumber (Float) | Kerning (letter spacing) |
NSParagraphStyle is a container for paragraph attributes: alignment, lineSpacing, paragraphSpacing, firstLineHeadIndent, lineBreakMode, minimumLineHeight, and others. To modify these parameters, an NSMutableParagraphStyle is created, the desired properties are set, and the object is passed as the value of the NSParagraphStyleAttributeName attribute. This is the only way to control line spacing in NSAttributedString.
NSShadow allows adding a shadow to text: the parameters shadowOffset, shadowBlurRadius, shadowColor set the offset, blur, and color of the shadow. Underline and strikethrough attributes accept style combinations: NSUnderlineStyle.single, .double, .thick, .patternDash, .patternDot. For precise control over line thickness and color, NSUnderlineColorAttributeName and NSStrikethroughColorAttributeName are used.
Creating an NSAttributedString in Swift is done via an initializer with the text and an attribute dictionary, or via NSMutableAttributedString with step-by-step style application. The basic approach is to define an attribute dictionary for the entire text, then add or modify attributes for specific ranges.
A simple example — setting font, color, and alignment for the entire string. The attribute dictionary is passed to the NSAttributedString initializer. Dictionary keys are NSAttributedString.Key constants, values are corresponding UIKit objects. This is the basic case when the entire text is formatted uniformly.
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.darkGray,
.paragraphStyle: let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = 4
return style
]
let attributedString = NSAttributedString(
string: "Hello world",
attributes: attributes
)
label.attributedText = attributedString
The text will be displayed with systemFont 16, dark gray color, center alignment, and 4pt line spacing. This approach is convenient for static headers and buttons.
NSMutableAttributedString allows applying different styles to different parts of the text. The addAttribute method adds a single attribute to a range, addAttributes adds a dictionary of attributes. The setAttributes method replaces all attributes of a range with new ones. This is the main tool for creating text with highlights.
let text = "Price: 1999 rubles"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.foregroundColor,
value: UIColor.green, range: NSRange(location: 6, length: 4))
attributed.addAttribute(.font,
value: UIFont.boldSystemFont(ofSize: 20), range: NSRange(location: 6, length: 4))
label.attributedText = attributed
The word “1999” will be green and bold, the rest of the text will be standard. NSRange is calculated manually — it is important to correctly count the length in characters, especially when working with emojis and composite Unicode characters.
NSMutableAttributedString provides methods for dynamically changing text and attributes: append, insert, replace, delete, setAttributes, addAttribute, removeAttribute, enumerateAttributes. This allows building text from different sources, combining styles, and responding to interface events.
Unlike the immutable NSAttributedString, the mutable version supports changing content without creating a new object. This is critical for text editors, chats, and forms where the user can edit text while styles must be preserved.
In messengers, each message contains the username (bold font), message text (normal), time (gray color). NSMutableAttributedString allows building such a string in one go by adding parts in the desired order with the corresponding attributes.
let result = NSMutableAttributedString()
let name = NSAttributedString(string: "Anna: ",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)])
let message = NSAttributedString(string: "Hello, how are you?",
attributes: [.font: UIFont.systemFont(ofSize: 15)])
let time = NSAttributedString(string: " 12:30",
attributes: [.foregroundColor: UIColor.gray])
result.append(name)
result.append(message)
result.append(time)
label.attributedText = result
The result is a single string with three styled sections. Append correctly calculates NSRange automatically, positions do not need to be calculated manually. This approach scales to any number of fragments.
The enumerateAttributes(in:options:using:) method iterates through all attribute ranges in the specified interval. This is useful for formatting analysis: finding all links, changing the color of specific attributes, or exporting text to HTML. The closure receives the attribute dictionary and the NSRange of the current section.
All major UI components for displaying text in UIKit support NSAttributedString via the attributedText property. UILabel displays static styled text, UITextView supports editing and links, UITextField accepts attributes for the placeholder and entered text separately.
UILabel is the lightest component for displaying styled text. It supports all character-level attributes but does not handle clickable links automatically (UITextView is needed for that). UILabel is ideal for headers, labels, and short formatted texts.
UITextView handles NSLinkAttributeName and displays links as interactive elements. To enable this functionality, set isSelectable = true and isEditable = false. When a link is tapped, the delegate receives the textView(_:shouldInteractWith:in:interaction:) call. UITextView also supports NSTextAttachment for images inside text.
let text = "Details on developer.apple.com"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.link,
value: URL(string: "https://developer.apple.com")!,
range: NSRange(location: 0, length: text.count))
textView.attributedText = attributed
textView.isSelectable = true
textView.isEditable = false
After setting isSelectable and isEditable, the text area behaves like a static text block, but links remain active. The UITextViewDelegate controls the behavior on tap.
Core Text is a low-level Apple framework for text rendering that works directly with NSAttributedString. Unlike UIKit, Core Text does not use NSAttributedString directly as a display object — instead, it converts it into a CTFramesetter, then CTFrame, and renders it in a Core Graphics context. This gives full control over line layout and glyphs.
Using Core Text is justified for custom text layouts: columns, image wrapping, text rotation, non-standard line breaks. Core Text’s NSMutableParagraphStyle includes attributes not available in UIKit: kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierLineBreakMode with additional modes.
NSAttributedString transfers seamlessly between UIKit and Core Text, as both frameworks work with the same type. UIKit attributes (NSFontAttributeName, NSForegroundColorAttributeName) are automatically recognized by Core Text, and vice versa — Core Text attributes (kCTFontAttributeName) are read by UIKit. This allows using UIKit for simple tasks and Core Text for custom rendering on the same NSAttributedString object.
Frequently Asked Questions
NSString stores only text without styling information. NSAttributedString supplements text with an attribute dictionary for each character range. When passed to UILabel via the text property, NSString displays as plain text. When NSAttributedString is passed via attributedText, all attributes are applied: different fonts, colors, and spacing in a single string.
Use the addAttributes(_:range:) method with an attribute dictionary: addAttributes([.font: font, .foregroundColor: color], range: range). To add or change a single attribute, use addAttribute(_:value:range:). The setAttributes method replaces all existing attributes in the range with the provided ones.
Create an NSMutableParagraphStyle, set the lineSpacing property, then pass it as the value of the NSParagraphStyleAttributeName attribute. For full control, minimumLineHeight, maximumLineHeight, paragraphSpacing, lineBreakMode, and alignment are also available. ParagraphStyle is the only way to control line spacing.
Yes, SwiftUI supports NSAttributedString via Text(attributedString:) in iOS 15+. In older versions, use UIViewRepresentable with UILabel or UITextView. SwiftUI also provides its own AttributedString type (SwiftUI, not Foundation) for declarative formatting with Markdown-like syntax.
Use the boundingRect(with:options:context:) method, which returns the CGRect needed to display the string with the given attributes. The options parameter: [.usesLineFragmentOrigin, .usesFontLeading] accounts for line spacing and font metrics. For UILabel with a limited number of lines, use sizeThatFits.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also