NSTextAttachment: what it is and how to add an image to text on iOS

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

NSTextAttachment is a class from the UIKit framework that allows embedding images and other media objects into formatted text through NSAttributedString. It works at the TextKit and Core Text level, giving developers control over the size, position, and behavior of attachments within the text flow. According to Apple Documentation (2025), NSTextAttachment supports images, PDF, and custom view containers, integrating with UITextView and UILabel. Understanding this API is necessary for creating Rich Text in iOS applications — from chats and editors to news feeds with icons in captions.

Key Takeaways

  • NSTextAttachment is a UIKit class for embedding media into formatted iOS text.
  • An image is added through NSAttributedString with the NSAttachmentAttributeName key.
  • The bounds property controls the size and vertical offset of the attachment.
  • NSTextAttachment supports images, PDF and custom files through a data container.
  • The API integrates with UITextView, UILabel and TextKit for flexible text layout.

What is NSTextAttachment?

NSTextAttachment is a class from the UIKit framework that allows embedding media objects directly into the text content of NSAttributedString. Unlike a separate UIImageView placed next to text, NSTextAttachment makes the image part of the text flow: the image wraps with lines, participates in alignment, and takes up space like a regular character.

The class is part of the TextKit architecture, which manages text rendering on iOS and macOS. TextKit breaks text into glyphs, takes into account kerning, ligatures, and leading — and NSTextAttachment fits into this pipeline as a special character that renders not as a letter but as a graphic object.

Each NSTextAttachment instance contains contents (file data), fileType (UTI content type), and bounds (a rectangle in points defining size and position). According to Apple Human Interface Guidelines, bounds default to the image size but can be changed for precise fit with the font.

Use NSTextAttachment instead of a separate UIImageView when the image should behave as part of the text — in chats, news feeds, text editors, and forms with icons in input fields.

How to Add an Image to Text via NSTextAttachment

The basic workflow with NSTextAttachment consists of three steps: create an instance, set the image, and attach it to NSAttributedString. Let’s look at the process using Swift.

swift
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "icon-star")

let attachmentString = NSAttributedString(attachment: attachment)

let text = NSMutableAttributedString(string: "Rating: ")
text.append(attachmentString)

let label = UILabel()
label.attributedText = text

After calling NSAttributedString(attachment:), the NSTextAttachment object is converted to the NSAttachmentAttributeName attribute, which is attached to a special object replacement character (code 0xFFFC). This character is not displayed as a letter — instead, the image from the image property is drawn in its place.

If the image should be placed in the middle of a text line (for example, an icon after a word), simply insert the attachmentString at the desired position in NSMutableAttributedString. TextKit will automatically account for the line height and align the image to the baseline.

Important: the image property is only available on iOS (since iOS 7). On macOS, use the contents property with NSImage. For backward compatibility, always prefer setting image directly rather than relying on the data container.

Configuring bounds and Attachment Position

By default, NSTextAttachment displays the image at its original size in points. In practice, you almost always need to adjust the size and vertical position — this is done using the bounds property.

The CGRect bounds structure includes origin (offset by X and Y) and size (width and height). The Y offset is particularly important: a negative value lowers the image below the baseline, a positive value raises it. A typical scenario is to align an icon to the center of a text line.

swift
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "icon-star")

let font = UIFont.systemFont(ofSize: 16)
let fontCapHeight = font.capHeight
let imageSize = CGSize(width: 18, height: 18)

attachment.bounds = CGRect(
    x: 0,
    y: (fontCapHeight - imageSize.height) / 2,
    width: imageSize.width,
    height: imageSize.height
)

The alignment calculation uses the font’s capHeight — the height of a capital letter, not the full line height. This ensures the icon visually matches the top edge of the text rather than floating between the baseline and ascender. The image size in the example is 18×18 pt, which is typical for icons in UI text.

If the image should be larger than the text line (for example, a photo preview in a chat), TextKit will automatically increase the line spacing for the current line. In this case, bounds should be set to the natural size, and the Y offset to zero.

PDF and Custom Attachments

NSTextAttachment supports not only PNG and JPEG but also PDF documents, as well as arbitrary files through the contents property. This makes it a universal tool for Rich Text in iOS applications.

When setting a PDF image to attachment.image, the system automatically renders the first page of the document. However, for precise rendering, use the data directly through the initializer with data and UTI type:

swift
guard let pdfData = Bundle.main.url(forResource: "document",
                                  withExtension: "pdf") else { return }

let fileData = Data(contentsOf: pdfData)
let attachment = NSTextAttachment(data: fileData,
                                       ofType: "com.adobe.pdf")

attachment.bounds = CGRect(x: 0, y: -4,
                           width: 24, height: 24)

let pdfString = NSAttributedString(attachment: attachment)

The ofType parameter accepts a UTI string (Uniform Type Identifier). Standard types include: public.image (any image), public.jpeg, public.png, com.adobe.pdf. When specifying the correct UTI, the system selects the appropriate rendering method — for PDF it’s CGPDFDocument, for images it’s CGImageSource.

For custom file types (for example, vector graphics in SVG format), you will need an NSTextAttachment subclass that overrides the image(forBounds:textContainer:characterIndex:) method. If the standard rendering is not suitable, return nil and implement drawing via Core Graphics in the draw method.

NSTextAttachment in UITextView and Delegation

NSTextAttachment works correctly in both UILabel and UITextView. However, UITextView provides more capabilities: interaction with attachments (tapping on an icon), editing text along with images, and support for NSAttachmentBehavior.

To handle taps on NSTextAttachment in UITextView, use the UITextViewDelegate protocol and the textView(_:shouldInteractWith:in:interaction:) method. This method is called when the user taps an attachment and allows navigating to a screen, opening a popup, or playing an animation.

swift
func textView(_ textView: UITextView,
                shouldInteractWith attachment: NSTextAttachment,
                in characterRange: NSRange,
                interaction: UITextItemInteraction) -> Bool {
    if interaction == .preview {
        return false
    }
    // Open detail screen
    showImageDetail(attachment.image)
    return false
}

The method distinguishes interaction types through the interaction parameter: .preview (3D Touch / Haptic Touch), .default (regular tap), and .presentActions (context menu). For each type, you can define its own behavior or disable it by returning false.

When editing UITextView with NSTextAttachment, it is important to remember: deleting the replacement character (0xFFFC) also deletes the attachment. The user sees the image as a single element — it is selected as a whole, not pixel by pixel. For drag-and-drop support of attachments on iOS 15+, use NSTextAttachmentViewProvider.

Common Mistakes When Working with NSTextAttachment

The first common mistake is ignoring bounds. Developers often rely on the original image size, which leads to giant icons in text or, conversely, images that are barely visible. Always set bounds explicitly taking into account the font and context.

The second mistake is incorrect Y offset. A positive value in bounds.origin.y lowers the image (in UIKit’s coordinate system, the Y axis points downward — this seems counterintuitive, but this is how Core Graphics works). To center-align within a line, use the formula with the font’s capHeight as shown in Section 3.

The third problem is image loss on traitCollection change. When the user switches Dark Mode or Dynamic Type, the font size may change, but bounds remain the same. The solution is to compute bounds dynamically in the layoutSubviews method or via KVO on font.

The fourth frequent mistake is using NSTextAttachment in UILabel with numberOfLines > 1. In multiline mode with limited width, TextKit correctly wraps lines together with the image. The problem arises when the attachment height exceeds the line height — adjacent lines overlap each other. The solution is to increase lineSpacing via NSMutableParagraphStyle.

Frequently Asked Questions

How is NSTextAttachment different from UIImageView in text?

NSTextAttachment makes the image part of the text flow: it wraps, aligns, and scales with the text. UIImageView is bound to superview coordinates and does not participate in text layout.

Can I add NSTextAttachment to UILabel?

Yes, if you set the attributedText property instead of text. UILabel correctly displays NSTextAttachment but does not support interactivity. For taps on the attachment, use UITextView.

How do I change the image size after creating the attachment?

Change the bounds property of the existing NSTextAttachment instance. The text will automatically re-render with the new sizes without needing to create a new NSAttributedString.

Does NSTextAttachment support animated images?

NSTextAttachment supports static images. For GIF and animated formats, a custom implementation via NSTextAttachmentViewProvider on iOS 15+ or via CADisplayLink is required.

How do I add NSTextAttachment to text programmatically?

Create an NSTextAttachment instance, set the image or data, set bounds, wrap it in NSAttributedString(attachment:), and insert it into NSMutableAttributedString using the insert(_:at:) method.

Summary

  • NSTextAttachment is a UIKit class for embedding images, PDF, and other media into formatted text.
  • An image is added via NSAttributedString(attachment:) and becomes part of the text flow.
  • The bounds property controls size and position: always set it explicitly considering the font.
  • To center an icon within a line, use the formula with the current font’s capHeight.
  • PDF attachments are supported via the initializer with data and the correct UTI type.
  • For handling taps on attachments, use UITextViewDelegate and the shouldInteractWith method.
  • When Dynamic Type changes, recalculate bounds dynamically to avoid line overlapping.

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