NSTextAttachment: o que é e como adicionar uma imagem ao texto no iOS

Autor: IT Sectr Publicado: 2026-07-25 Tempo de leitura: 9 min

NSTextAttachment é uma classe do framework UIKit que permite incorporar imagens e outros objetos de mídia em texto formatado através do NSAttributedString. Ele funciona no nível do TextKit e Core Text, dando aos desenvolvedores controle sobre o tamanho, posição e comportamento dos anexos dentro do fluxo de texto. De acordo com a Apple Documentation (2025), o NSTextAttachment suporta imagens, PDF e contêineres de visualização personalizados, integrando-se com UITextView e UILabel. Compreender esta API é necessário para criar Rich Text em aplicativos iOS — desde chats e editores até feeds de notícias com ícones em legendas.

Pontos principais

  • NSTextAttachment é uma classe UIKit para incorporar mídia em texto formatado do iOS.
  • Uma imagem é adicionada através de NSAttributedString com a chave NSAttachmentAttributeName.
  • A propriedade bounds controla o tamanho e o deslocamento vertical do anexo.
  • NSTextAttachment suporta imagens, PDF e arquivos personalizados através de um contêiner de dados.
  • A API integra-se com UITextView, UILabel e TextKit para layout de texto flexível.

O que é NSTextAttachment?

NSTextAttachment é uma classe do framework UIKit que permite incorporar objetos de mídia diretamente no conteúdo de texto do NSAttributedString. Ao contrário de um UIImageView separado colocado ao lado do texto, o NSTextAttachment torna a imagem parte do fluxo de texto: a imagem se ajusta com as linhas, participa do alinhamento e ocupa espaço como um caractere comum.

A classe faz parte da arquitetura TextKit, que gerencia a renderização de texto no iOS e macOS. O TextKit divide o texto em glifos, leva em consideração kerning, ligaduras e entrelinha — e o NSTextAttachment se encaixa neste pipeline como um caractere especial que é renderizado não como uma letra, mas como um objeto gráfico.

Cada instância do NSTextAttachment contém contents (dados do arquivo), fileType (tipo de conteúdo UTI) e bounds (um retângulo em points que define tamanho e posição). De acordo com as Apple Human Interface Guidelines, bounds por padrão é o tamanho da imagem, mas pode ser alterado para um ajuste preciso com a fonte.

Use NSTextAttachment em vez de um UIImageView separado quando a imagem deve se comportar como parte do texto — em chats, feeds de notícias, editores de texto e formulários com ícones em campos de entrada.

Como adicionar uma imagem ao texto via NSTextAttachment

O fluxo de trabalho básico com NSTextAttachment consiste em três etapas: criar uma instância, definir a imagem e anexá-la ao NSAttributedString. Vamos examinar o processo usando 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

Após chamar NSAttributedString(attachment:), o objeto NSTextAttachment é convertido para o atributo NSAttachmentAttributeName, que é anexado a um caractere especial de substituição de objeto (código 0xFFFC). Este caractere não é exibido como uma letra — em vez disso, a imagem da propriedade image é desenhada em seu lugar.

Se a imagem deve ser colocada no meio de uma linha de texto (por exemplo, um ícone após uma palavra), simplesmente insira o attachmentString na posição desejada no NSMutableAttributedString. O TextKit levará em conta automaticamente a altura da linha e alinhará a imagem à linha de base.

Importante: a propriedade image está disponível apenas no iOS (desde o iOS 7). No macOS, use a propriedade contents com NSImage. Para compatibilidade com versões anteriores, sempre prefira definir image diretamente em vez de confiar no contêiner de dados.

Configuração de bounds e posição do anexo

Por padrão, o NSTextAttachment exibe a imagem em seu tamanho original em points. Na prática, quase sempre é necessário ajustar o tamanho e a posição vertical — isso é feito usando a propriedade bounds.

A estrutura CGRect bounds inclui origin (deslocamento em X e Y) e size (largura e altura). O deslocamento em Y é particularmente importante: um valor negativo abaixa a imagem abaixo da linha de base, um valor positivo a eleva. Um cenário típico é alinhar um ícone ao centro de uma linha de texto.

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
)

O cálculo de alinhamento usa o capHeight da fonte — a altura de uma letra maiúscula, não a altura completa da linha. Isso garante que o ícone corresponda visualmente à borda superior do texto, em vez de flutuar entre a linha de base e o ascendente. O tamanho da imagem no exemplo é 18×18 pt, que é típico para ícones em texto de UI.

Se a imagem deve ser maior que a linha de texto (por exemplo, uma prévia de foto em um chat), o TextKit aumentará automaticamente o espaçamento entre linhas para a linha atual. Neste caso, bounds deve ser definido para o tamanho natural e o deslocamento em Y para zero.

PDF e anexos personalizados

NSTextAttachment suporta não apenas PNG e JPEG, mas também documentos PDF, bem como arquivos arbitrários através da propriedade contents. Isso o torna uma ferramenta universal para Rich Text em aplicativos iOS.

Ao definir uma imagem PDF em attachment.image, o sistema renderiza automaticamente a primeira página do documento. No entanto, para renderização precisa, use os dados diretamente através do inicializador com dados 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)

O parâmetro ofType aceita uma string UTI (Uniform Type Identifier). Os tipos padrão incluem: public.image (qualquer imagem), public.jpeg, public.png, com.adobe.pdf. Ao especificar a UTI correta, o sistema seleciona o método de renderização apropriado — para PDF é CGPDFDocument, para imagens é CGImageSource.

Para tipos de arquivo personalizados (por exemplo, gráficos vetoriais no formato SVG), você precisará de uma subclasse de NSTextAttachment que sobrescreva o método image(forBounds:textContainer:characterIndex:). Se a renderização padrão não for adequada, retorne nil e implemente o desenho através do Core Graphics no método draw.

NSTextAttachment em UITextView e delegação

NSTextAttachment funciona corretamente tanto em UILabel quanto em UITextView. No entanto, o UITextView oferece mais capacidades: interação com anexos (tocar em um ícone), edição de texto junto com imagens e suporte para NSAttachmentBehavior.

Para lidar com toques em NSTextAttachment no UITextView, use o protocolo UITextViewDelegate e o método textView(_:shouldInteractWith:in:interaction:). Este método é chamado quando o usuário toca em um anexo e permite navegar para uma tela, abrir um popup ou reproduzir uma animação.

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

O método distingue tipos de interação através do parâmetro interaction: .preview (3D Touch / Haptic Touch), .default (toque normal) e .presentActions (menu de contexto). Para cada tipo, você pode definir seu próprio comportamento ou desativá-lo retornando false.

Ao editar UITextView com NSTextAttachment, é importante lembrar: excluir o caractere de substituição (0xFFFC) também exclui o anexo. O usuário vê a imagem como um único elemento — ela é selecionada como um todo, não pixel por pixel. Para suporte de arrastar e soltar anexos no iOS 15+, use NSTextAttachmentViewProvider.

Erros comuns ao trabalhar com NSTextAttachment

O primeiro erro comum é ignorar bounds. Os desenvolvedores muitas vezes confiam no tamanho original da imagem, o que leva a ícones gigantes no texto ou, inversamente, imagens que são quase invisíveis. Sempre defina bounds explicitamente levando em consideração a fonte e o contexto.

O segundo erro é deslocamento Y incorreto. Um valor positivo em bounds.origin.y abaixa a imagem (no sistema de coordenadas do UIKit, o eixo Y aponta para baixo — isso parece contraintuitivo, mas é assim que o Core Graphics funciona). Para alinhar ao centro dentro de uma linha, use a fórmula com capHeight da fonte conforme mostrado na Seção 3.

O terceiro problema é perda de imagem ao mudar traitCollection. Quando o usuário alterna o Modo Escuro ou Dynamic Type, o tamanho da fonte pode mudar, mas bounds permanece o mesmo. A solução é calcular bounds dinamicamente no método layoutSubviews ou via KVO na fonte.

O quarto erro frequente é usar NSTextAttachment em UILabel com numberOfLines > 1. No modo multilinha com largura limitada, o TextKit quebra corretamente as linhas junto com a imagem. O problema surge quando a altura do anexo excede a altura da linha — as linhas adjacentes se sobrepõem. A solução é aumentar o lineSpacing através do NSMutableParagraphStyle.

Perguntas frequentes

Como o NSTextAttachment difere do UIImageView no texto?

NSTextAttachment torna a imagem parte do fluxo de texto: ela se ajusta, alinha e escala com o texto. UIImageView está vinculado às coordenadas da superview e não participa do layout do texto.

Posso adicionar NSTextAttachment ao UILabel?

Sim, se você definir a propriedade attributedText em vez de text. UILabel exibe corretamente o NSTextAttachment, mas não suporta interatividade. Para toques no anexo, use UITextView.

Como alterar o tamanho da imagem após criar o anexo?

Altere a propriedade bounds da instância existente do NSTextAttachment. O texto será automaticamente renderizado novamente com os novos tamanhos sem necessidade de criar um novo NSAttributedString.

O NSTextAttachment suporta imagens animadas?

NSTextAttachment suporta imagens estáticas. Para GIF e formatos animados, é necessária uma implementação personalizada através do NSTextAttachmentViewProvider no iOS 15+ ou através do CADisplayLink.

Como adicionar NSTextAttachment ao texto programaticamente?

Crie uma instância de NSTextAttachment, defina a imagem ou dados, configure bounds, envolva em NSAttributedString(attachment:) e insira no NSMutableAttributedString usando o método insert(_:at:).

Resumo

  • NSTextAttachment é uma classe UIKit para incorporar imagens, PDF e outras mídias em texto formatado.
  • Uma imagem é adicionada via NSAttributedString(attachment:) e se torna parte do fluxo de texto.
  • A propriedade bounds controla tamanho e posição: sempre defina explicitamente considerando a fonte.
  • Para centralizar um ícone dentro de uma linha, use a fórmula com o capHeight da fonte atual.
  • Anexos PDF são suportados através do inicializador com data e o tipo UTI correto.
  • Para lidar com toques em anexos, use UITextViewDelegate e o método shouldInteractWith.
  • Quando o Dynamic Type mudar, recalcule bounds dinamicamente para evitar sobreposição de linhas.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também