NSAttributedString — what it is, text formatting and attributes in iOS

Author: IT Sectr Published: 2026-07-23 Reading time: 9 min

NSAttributedString is a class from the Foundation framework in the iOS SDK that represents a string with a set of formatting attributes applied to individual characters or ranges of text. Unlike regular NSString, NSAttributedString stores not only Unicode characters but also a dictionary of attributes (font, color, kerning, alignment) for each segment of the string. According to Apple Developer Documentation (2026), NSAttributedString is the foundation for displaying formatted text in all iOS UI components.

Key Takeaways

  • NSAttributedString — an immutable string with attributes where each character or range corresponds to an NSAttributedStringKey dictionary
  • NSMutableAttributedString — a mutable version with addAttribute, setAttributes, replaceCharacters methods for modifying attributes at runtime
  • Key attributes: .font, .foregroundColor, .paragraphStyle, .kern, .underlineStyle, .strikethroughStyle, .link, .backgroundColor
  • NSMutableParagraphStyle — a helper object for setting alignment, line spacing, indentation and text direction
  • UILabel, UITextView, UITextField support attributedText for displaying attributed strings

What is NSAttributedString?

NSAttributedString is a fundamental iOS/macOS class for working with formatted text. It extends NSString by adding attributes to the string — a dictionary of key-value pairs where the key is an NSAttributedStringKey constant (e.g., .font, .foregroundColor) and the value is the corresponding object (UIFont, UIColor). Each character in the string can have its own set of attributes, enabling mixed formatting within a single string.

The NSAttributedString architecture is based on the concept of attribute runs. If you set the .font attribute to UIFont.boldSystemFont(ofSize: 16) for the character range 0..5, all characters in that range will appear in bold. Other characters may have a different font or no attribute at all. When rendering an attributed string, the UIKit system merges characteristics from different ranges and renders the text uniformly.

NSAttributedString is immutable — after creation, its attributes and content cannot be changed. For modification, there is the NSMutableAttributedString subclass, which provides methods for adding, removing, and changing attributes in any range. This distinction is important for multithreading: the immutable NSAttributedString is thread-safe, while NSMutableAttributedString is not.

Key Text Formatting Attributes

NSAttributedString supports about 40 standard attributes defined in NSAttributedStringKey. Each attribute affects a specific aspect of text appearance: font, color, position, underline, shadow, kerning, paragraph style, and hyperlinks. To set an attribute, you use an NSAttributedStringKey constant and assign it an object of the corresponding type.

Attribute KeyValue TypePurpose
.fontUIFontFont and text size
.foregroundColorUIColorText color
.backgroundColorUIColorBackground color behind text
.paragraphStyleNSParagraphStyleAlignment, line spacing, indentation
.kernNSNumber (Float)Character spacing (kerning)
.underlineStyleNSUnderlineStyle (Int)Underline style (single, double, thick, pattern)
.strikethroughStyleNSUnderlineStyle (Int)Strikethrough style
.linkNSURLURL for interactive hyperlink
.shadowNSShadowText shadow with offset, blurRadius and color
.baselineOffsetNSNumber (Float)Text offset from baseline

NSParagraphStyle — Paragraph Formatting

NSMutableParagraphStyle is an object that manages the visual characteristics of a paragraph: alignment (.alignment: .left, .center, .right, .justified), line spacing (.lineSpacing), paragraph spacing (.paragraphSpacing), first line indent (.firstLineHeadIndent), left and right indentation (.headIndent, .tailIndent), and text direction (.baseWritingDirection). ParagraphStyle is applied to a range that includes newline characters if the same formatting is required for the entire paragraph.

How to Create NSAttributedString in Code

Creating an NSAttributedString is done through an initializer that takes a string and a dictionary of attributes. The attributes are applied to the entire string. For mixed formatting (different attributes in different parts of the string), NSMutableAttributedString is used with subsequent addition of attributes to specific ranges. Objective-C uses an NSAttributedStringKey: UIFont dictionary, while Swift uses a type-safe [NSAttributedString.Key: Any] dictionary.

swift
let plainText = "Hello, Swift!"

// Create with uniform attributes for the entire string
let attributes: [NSAttributedString.Key: Any] = [
    NSAttributedString.Key.font:
        UIFont.systemFont(ofSize: 18),
    NSAttributedString.Key.foregroundColor:
        UIColor.darkText,
    NSAttributedString.Key.kern: 1.5
]

let attributedString =
    NSAttributedString(string: plainText,
                        attributes: attributes)

Creating with NSMutableParagraphStyle

An example demonstrates paragraph formatting via NSMutableParagraphStyle. Center alignment is set, line spacing of 8 points, paragraph spacing of 12 points. ParagraphStyle is added to the attribute dictionary under the .paragraphStyle key. NSAttributedString copies the passed paragraphStyle, so after creating the string you can modify it without affecting the already created string.

swift
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
paragraphStyle.lineSpacing = 8.0
paragraphStyle.paragraphSpacing = 12.0
paragraphStyle.firstLineHeadIndent = 20.0

let attributed = NSAttributedString(
    string: "Centered paragraph with spacing",
    attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])

NSMutableAttributedString and Modifying Attributes

NSMutableAttributedString is a subclass of NSAttributedString that allows modifying content and attributes after creation. Key methods: addAttribute(_:value:range:) to add a single attribute to a range; addAttributes(_:range:) to add multiple attributes; setAttributes(_:range:) to replace all attributes in a range; removeAttribute(_:range:) to remove an attribute; replaceCharacters(in:with:) to replace text.

addAttribute and addAttributes add attributes to existing ones without removing already set attributes. If a range already has an attribute with the same key, its value is replaced. setAttributes completely replaces the attribute dictionary for a range — all previously set attributes are removed. This is important to understand when sequentially formatting a single string: addAttributes is safer as it does not reset already set fonts and colors.

Ranges (NSRange) are specified using the NSRange(location: 0, length: 5) structure. location is the starting index (0-based), length is the number of characters. If the range exceeds the string boundaries, NSMutableAttributedString throws an NSRangeException. For safe range operations, use NSRange methods from Foundation such as NSIntersectionRange and NSUnionRange.

swift
let attributed = NSMutableAttributedString(
    string: "Bold and red text here")

// Apply bold font to first 9 characters
let boldRange = NSRange(location: 0, length: 9)
attributed.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 16),
    range: boldRange)

// Apply red color to characters 13-16 ("text")
let redRange = NSRange(location: 13, length: 4)
attributed.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.red,
    range: redRange)

// Apply underline to the entire string
let fullRange = NSRange(location: 0,
                       length: attributed.length)
attributed.addAttribute(
    NSAttributedString.Key.underlineStyle,
    value: NSUnderlineStyle.single.rawValue,
    range: fullRange)

Displaying an Attributed String in UILabel

The most common way to display an NSAttributedString is to assign it to the attributedText property of a UILabel. Unlike the text property, attributedText uses attributes for rendering, supporting mixed formatting. Important: if attributedText is set, UILabel ignores the font, textColor, and textAlignment properties — all visual characteristics come from the NSAttributedString attributes.

swift
let label = UILabel()
label.numberOfLines = 0

let fullText = NSMutableAttributedString(
    string: "Price: $24.99 per month")

// Format "Price:" label with bold font
let priceLabelRange = NSRange(
    location: 0, length: 6)
fullText.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 16),
    range: priceLabelRange)

// Format "$24.99" with green color
let amountRange = NSRange(
    location: 7, length: 6)
fullText.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.systemGreen(),
    range: amountRange)
fullText.addAttribute(
    NSAttributedString.Key.font,
    value: UIFont.boldSystemFont(ofSize: 22),
    range: amountRange)

// Apply gray color to "per month" text
let periodRange = NSRange(
    location: 14, length: 9)
fullText.addAttribute(
    NSAttributedString.Key.foregroundColor,
    value: UIColor.secondaryLabel,
    range: periodRange)

label.attributedText = fullText

Displaying in UITextView with Interactive Links

UITextView supports interactive links in NSAttributedString. The .link attribute with an NSURL makes text clickable. To handle taps, use the UITextViewDelegate with the textView(_:shouldInteractWith:in:interaction:) method. UITextView also supports text selection and using UIMenuController for standard operations (copy, search).

Converting NSAttributedString to HTML and RTF

NSAttributedString supports conversion from HTML and RTF via NSAttributedString.DocumentType. To load HTML, use the initializer with documentAttributes parameter: NSAttributedString(data: htmlData, options: [.documentType: .html], documentAttributes: nil). Similarly for RTF: .rtf or .rtfd. This mechanism is useful for displaying HTML content without WebView.

For exporting to HTML, use the data(from:documentAttributes:) method with a range and document type. HTML export: try attributedString.data(from: fullRange, documentAttributes: [.documentType: .html]). The resulting data can be saved to a file, sent to a server, or displayed in a WebView. During export, fonts, colors, alignment, lists — all formatting attributes — are converted to CSS styles.

RTF support is especially relevant for macOS applications, where RTF is the standard rich text format. iOS also supports reading and writing RTF but does not use it as a primary format. The difference between RTF and RTFD: RTFD includes embedded resources (images) packed into a directory. NSAttributedString can handle both formats through a single interface.

swift
let htmlString = "<p><b>Bold<\/b> and <i>italic<\/i><\/p>"
guard let htmlData = htmlString.data(
    using: String.Encoding.utf8) else { return }

let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
    NSAttributedString.DocumentReadingOptionKey.documentType:
        NSAttributedString.DocumentType.html
]

let attributedFromHTML =
    try? NSAttributedString(
        data: htmlData,
        options: options,
        documentAttributes: nil)

Frequently Asked Questions

What is the difference between NSString and NSAttributedString?

NSString stores only a sequence of Unicode characters without any formatting information. NSAttributedString stores characters and for each subrange contains a dictionary of attributes (font, color, style). When displayed, UIKit uses these attributes for rendering, creating formatted text.

Why doesn't UILabel display NSAttributedString attributes?

The most common reason is using the text property instead of attributedText. When assigning through text, all attributes are ignored. The second reason: after setting attributedText, you change UILabel's font, textColor, or textAlignment — these changes reset attributedText. Use only attributedText for formatted text.

How to apply different fonts to a single string?

Create an NSMutableAttributedString and call addAttribute(.font, value: boldFont, range: boldRange) for each segment with a different font. Each call applies the attribute only to the specified range. The remaining characters retain the standard font or another previously set one. This creates attribute runs with different fonts.

Does NSAttributedString work with multiline text?

Yes, NSAttributedString correctly handles multiline text, including newline characters ( ). UITextView and UILabel (with numberOfLines = 0) automatically wrap text to a new line. NSMutableParagraphStyle manages line spacing, indentation, and alignment for each paragraph independently.

How to create colored text with different colors in one string?

Use NSMutableAttributedString with the .foregroundColor attribute for each color range. For red text: addAttribute(.foregroundColor, value: UIColor.red, range: firstRange). For blue: addAttribute(.foregroundColor, value: UIColor.blue, range: secondRange). Colors will be applied only to the specified character ranges.

Summary

  • NSAttributedString — a string with formatting attributes (font, color, style) stored in a dictionary for each character range
  • NSMutableAttributedString — a mutable version with addAttribute, setAttributes, and removeAttribute methods for dynamic formatting
  • Key attributes: .font, .foregroundColor, .paragraphStyle, .kern, .underlineStyle, .strikethroughStyle, .link, .shadow, .baselineOffset
  • NSMutableParagraphStyle manages alignment, line spacing, indentation, and text direction for paragraphs
  • UILabel, UITextView, UITextField support displaying formatted text through the attributedText property
  • HTML/RTF conversion — NSAttributedString supports importing and exporting formatted text via documentType

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.

Discuss the project

Read also