NSTextAttachment: cos’è e come aggiungere un’immagine al testo su iOS

Autore: IT Sectr Pubblicato: 2026-07-25 Tempo di lettura: 9 min

NSTextAttachment è una classe del framework UIKit che consente di incorporare immagini e altri oggetti multimediali in testo formattato tramite NSAttributedString. Funziona a livello di TextKit e Core Text, dando agli sviluppatori il controllo su dimensione, posizione e comportamento degli allegati all’interno del flusso di testo. Secondo Apple Documentation (2025), NSTextAttachment supporta immagini, PDF e contenitori di visualizzazione personalizzati, integrandosi con UITextView e UILabel. Comprendere questa API è necessario per creare Rich Text nelle applicazioni iOS — dalle chat e editori ai feed di notizie con icone nelle didascalie.

Punti chiave

  • NSTextAttachment è una classe UIKit per incorporare media in testo formattato iOS.
  • Un’immagine viene aggiunta tramite NSAttributedString con la chiave NSAttachmentAttributeName.
  • La proprietà bounds controlla la dimensione e l’offset verticale dell’allegato.
  • NSTextAttachment supporta immagini, PDF e file personalizzati tramite un contenitore di dati.
  • L’API si integra con UITextView, UILabel e TextKit per un layout di testo flessibile.

Cos’è NSTextAttachment?

NSTextAttachment è una classe del framework UIKit che consente di incorporare oggetti multimediali direttamente nel contenuto testuale di NSAttributedString. A differenza di un UIImageView separato posizionato accanto al testo, NSTextAttachment rende l’immagine parte del flusso di testo: l’immagine va a capo con le righe, partecipa all’allineamento e occupa spazio come un carattere normale.

La classe fa parte dell’architettura TextKit, che gestisce il rendering del testo su iOS e macOS. TextKit scompone il testo in glifi, tiene conto di crenatura, legature e interlinea — e NSTextAttachment si inserisce in questa pipeline come un carattere speciale che viene renderizzato non come lettera ma come oggetto grafico.

Ogni istanza di NSTextAttachment contiene contents (dati del file), fileType (tipo di contenuto UTI) e bounds (un rettangolo in points che definisce dimensione e posizione). Secondo Apple Human Interface Guidelines, bounds per impostazione predefinita è la dimensione dell’immagine, ma può essere modificato per un adattamento preciso al font.

Utilizza NSTextAttachment invece di un UIImageView separato quando l’immagine deve comportarsi come parte del testo — in chat, feed di notizie, editor di testo e moduli con icone nei campi di input.

Come aggiungere un’immagine al testo tramite NSTextAttachment

Il flusso di lavoro di base con NSTextAttachment si compone di tre passaggi: creare un’istanza, impostare l’immagine e allegarla a NSAttributedString. Esaminiamo il processo utilizzando 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

Dopo aver chiamato NSAttributedString(attachment:), l’oggetto NSTextAttachment viene convertito nell’attributo NSAttachmentAttributeName, che viene allegato a un carattere speciale di sostituzione dell’oggetto (codice 0xFFFC). Questo carattere non viene visualizzato come lettera — invece, l’immagine dalla proprietà image viene disegnata al suo posto.

Se l’immagine deve essere posizionata nel mezzo di una riga di testo (ad esempio, un’icona dopo una parola), inserisci semplicemente attachmentString nella posizione desiderata in NSMutableAttributedString. TextKit terrà automaticamente conto dell’altezza della riga e allineerà l’immagine alla linea di base.

Importante: la proprietà image è disponibile solo su iOS (da iOS 7). Su macOS, utilizza la proprietà contents con NSImage. Per compatibilità con le versioni precedenti, preferisci sempre impostare image direttamente piuttosto che fare affidamento sul contenitore di dati.

Configurazione di bounds e posizione dell’allegato

Per impostazione predefinita, NSTextAttachment visualizza l’immagine nella sua dimensione originale in points. In pratica, è quasi sempre necessario regolare la dimensione e la posizione verticale — ciò viene fatto utilizzando la proprietà bounds.

La struttura CGRect bounds include origin (offset in X e Y) e size (larghezza e altezza). L’offset Y è particolarmente importante: un valore negativo abbassa l’immagine sotto la linea di base, un valore positivo la solleva. Uno scenario tipico è allineare un’icona al centro di una riga di testo.

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
)

Il calcolo dell’allineamento utilizza il capHeight del font — l’altezza di una lettera maiuscola, non l’altezza completa della riga. Ciò garantisce che l’icona corrisponda visivamente al bordo superiore del testo invece di fluttuare tra la linea di base e l’ascendente. La dimensione dell’immagine nell’esempio è 18×18 pt, tipica per le icone nel testo dell’interfaccia utente.

Se l’immagine deve essere più grande della riga di testo (ad esempio, un’anteprima di foto in una chat), TextKit aumenterà automaticamente la spaziatura tra le righe per la riga corrente. In questo caso, bounds deve essere impostato alla dimensione naturale e l’offset Y a zero.

PDF e allegati personalizzati

NSTextAttachment supporta non solo PNG e JPEG, ma anche documenti PDF, oltre a file arbitrari tramite la proprietà contents. Ciò lo rende uno strumento universale per Rich Text nelle applicazioni iOS.

Quando si imposta un’immagine PDF in attachment.image, il sistema renderizza automaticamente la prima pagina del documento. Tuttavia, per un rendering preciso, utilizza i dati direttamente tramite l’inizializzatore con dati e tipo UTI:

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)

Il parametro ofType accetta una stringa UTI (Uniform Type Identifier). I tipi standard includono: public.image (qualsiasi immagine), public.jpeg, public.png, com.adobe.pdf. Specificando l’UTI corretta, il sistema seleziona il metodo di rendering appropriato — per PDF è CGPDFDocument, per le immagini è CGImageSource.

Per tipi di file personalizzati (ad esempio, grafica vettoriale in formato SVG), avrai bisogno di una sottoclasse di NSTextAttachment che sovrascriva il metodo image(forBounds:textContainer:characterIndex:). Se il rendering standard non è adatto, restituisci nil e implementa il disegno tramite Core Graphics nel metodo draw.

NSTextAttachment in UITextView e delega

NSTextAttachment funziona correttamente sia in UILabel che in UITextView. Tuttavia, UITextView offre maggiori capacità: interazione con gli allegati (toccare un’icona), modifica del testo insieme alle immagini e supporto per NSAttachmentBehavior.

Per gestire i tocchi su NSTextAttachment in UITextView, utilizza il protocollo UITextViewDelegate e il metodo textView(_:shouldInteractWith:in:interaction:). Questo metodo viene chiamato quando l’utente tocca un allegato e consente di navigare verso una schermata, aprire un popup o riprodurre un’animazione.

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

Il metodo distingue i tipi di interazione tramite il parametro interaction: .preview (3D Touch / Haptic Touch), .default (tocco normale) e .presentActions (menu contestuale). Per ogni tipo, puoi definire il tuo comportamento o disabilitarlo restituendo false.

Quando si modifica UITextView con NSTextAttachment, è importante ricordare: eliminare il carattere di sostituzione (0xFFFC) elimina anche l’allegato. L’utente vede l’immagine come un singolo elemento — viene selezionata nel suo insieme, non pixel per pixel. Per il supporto drag-and-drop degli allegati su iOS 15+, utilizza NSTextAttachmentViewProvider.

Errori comuni con NSTextAttachment

Il primo errore comune è ignorare bounds. Gli sviluppatori spesso si affidano alla dimensione originale dell’immagine, portando a icone giganti nel testo o, al contrario, immagini appena visibili. Imposta sempre bounds esplicitamente tenendo conto del font e del contesto.

Il secondo errore è un offset Y errato. Un valore positivo in bounds.origin.y abbassa l’immagine (nel sistema di coordinate di UIKit, l’asse Y punta verso il basso — sembra controintuitivo, ma è così che funziona Core Graphics). Per allineare al centro di una riga, utilizza la formula con il capHeight del font come mostrato nella Sezione 3.

Il terzo problema è la perdita dell’immagine al cambiamento di traitCollection. Quando l’utente passa alla Modalità scura o a Dynamic Type, la dimensione del font può cambiare, ma bounds rimane invariato. La soluzione è calcolare bounds dinamicamente nel metodo layoutSubviews o tramite KVO sul font.

Il quarto errore frequente è utilizzare NSTextAttachment in UILabel con numberOfLines > 1. In modalità multilinea con larghezza limitata, TextKit va a capo correttamente con l’immagine. Il problema sorge quando l’altezza dell’allegato supera l’altezza della riga — le righe adiacenti si sovrappongono. La soluzione è aumentare lineSpacing tramite NSMutableParagraphStyle.

Domande frequenti

In cosa si differenzia NSTextAttachment da UIImageView nel testo?

NSTextAttachment rende l’immagine parte del flusso di testo: va a capo, si allinea e si ridimensiona con il testo. UIImageView è vincolato alle coordinate della superview e non partecipa al layout del testo.

Si può aggiungere NSTextAttachment a UILabel?

Sì, se si imposta la proprietà attributedText invece di text. UILabel visualizza correttamente NSTextAttachment ma non supporta l’interattività. Per i tocchi sull’allegato, utilizza UITextView.

Come cambiare la dimensione dell’immagine dopo aver creato l’allegato?

Modifica la proprietà bounds dell’istanza esistente di NSTextAttachment. Il testo verrà automaticamente renderizzato con le nuove dimensioni senza bisogno di creare un nuovo NSAttributedString.

NSTextAttachment supporta immagini animate?

NSTextAttachment supporta immagini statiche. Per GIF e formati animati, è necessaria un’implementazione personalizzata tramite NSTextAttachmentViewProvider su iOS 15+ o tramite CADisplayLink.

Come aggiungere NSTextAttachment al testo a livello di codice?

Crea un’istanza di NSTextAttachment, imposta l’immagine o i dati, configura bounds, avvolgila in NSAttributedString(attachment:) e inseriscila in NSMutableAttributedString usando il metodo insert(_:at:).

Riepilogo

  • NSTextAttachment è una classe UIKit per incorporare immagini, PDF e altri media in testo formattato.
  • Un’immagine viene aggiunta tramite NSAttributedString(attachment:) e diventa parte del flusso di testo.
  • La proprietà bounds controlla dimensione e posizione: impostala sempre esplicitamente considerando il font.
  • Per centrare un’icona in una riga, utilizza la formula con il capHeight del font corrente.
  • Gli allegati PDF sono supportati tramite l’inizializzatore con data e il tipo UTI corretto.
  • Per gestire i tocchi sugli allegati, utilizza UITextViewDelegate e il metodo shouldInteractWith.
  • Quando Dynamic Type cambia, ricalcola bounds dinamicamente per evitare sovrapposizioni di righe.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche