Genmoji e NSAdaptiveImageGlyph: como apps exibem emojis inline gerados pelo usuário
Genmoji é o nome voltado ao usuário do recurso de emoji personalizado do Apple Intelligence: o usuário digita uma descrição, o sistema gera uma imagem inline parecida com um emoji e o resultado aparece no texto ao lado dos emojis Unicode. A superfície voltada ao desenvolvedor é o NSAdaptiveImageGlyph, uma classe do iOS 18+ que representa imagens inline adaptativas em texto atribuído1. Genmoji é uma das fontes de instâncias de NSAdaptiveImageGlyph; apps que lidam com texto atribuído precisam dar suporte à classe para exibir Genmoji (e qualquer conteúdo futuro de adaptive-image-glyph que a Apple venha a introduzir).
O post percorre a API em comparação com a documentação da Apple. O recorte é “o que um app existente de tratamento de texto deve fazer para exibir Genmoji corretamente”, porque a maioria dos apps que recebem texto digitado pelo usuário em um UITextView precisa optar por adaptive image glyphs para conseguir renderizar o Genmoji do usuário, e o lado da persistência tem implicações de serialização que costumam passar despercebidas.
TL;DR
NSAdaptiveImageGlyph(iOS 18+) é um tipo de dado que encapsula uma imagem adaptativa mais metadados de identificação. A entrada de Genmoji vinda do teclado do sistema chega como instâncias deNSAdaptiveImageGlyphembutidas em texto atribuído2.supportsAdaptiveImageGlyphé declarado no protocoloUITextInput;UITextViewadota o protocolo, então a propriedade pode ser definida comotextView.supportsAdaptiveImageGlyph = true. O padrão éfalse; sem a opção habilitada, o Genmoji digitado pelo usuário não é renderizado.- Adaptive image glyphs exigem TextKit 2. Apps que ainda estão em TextKit 1 não renderizam
NSAdaptiveImageGlyphcorretamente. Novos apps com target iOS 18+ devem adotar TextKit 2 por padrão. NSAttributedStringcarrega adaptive image glyphs por meio do atributoNSAttributedString.Key.adaptiveImageGlyph. O inicializadorNSAttributedString(adaptiveImageGlyph:attributes:)constrói uma attributed string contendo um único glyph3.- Persistência e round-tripping exigem cuidado. O armazenamento em texto puro remove o Genmoji por completo; formatos de texto rico (RTFD, Markdown com extensões, HTML com dados de imagem embutidos) preservam.
O que o NSAdaptiveImageGlyph carrega
Um NSAdaptiveImageGlyph é um wrapper de dados com quatro propriedades de identificação2:
imageContent: Data. Os próprios dados da imagem, no formato declarado porcontentType.contentIdentifier: String. Um identificador único para a instância do glyph. Usado para deduplicação e para o cache interno do sistema.contentDescription: String. Texto alternativo descrevendo o glyph. Apps que expõem rótulos de acessibilidade ou que enviam glyphs para destinatários sem suporte a glyphs usam esse campo.contentType: UTType. Uma propriedade de tipo, em nível de classe, que expõe o formato de imagem que a Apple usa para adaptive glyphs (uma variante de HEIC). Apps que serializam consultam isso para guiar um tratamento ciente do formato.
Os dados costumam ter dezenas de kilobytes para um Genmoji padrão. Múltiplos tamanhos são codificados no mesmo arquivo de imagem usando os recursos de adaptive image do HEIC; o sistema escolhe o tamanho certo com base no contexto de renderização.
Habilitando adaptive image glyphs em UITextView
A opção é uma única propriedade1:
import UIKit
let textView = UITextView()
textView.supportsAdaptiveImageGlyph = true
// Also requires TextKit 2 (default on UITextView for iOS 16+
// when constructed via Interface Builder or modern initializer)
Sem supportsAdaptiveImageGlyph = true, o Genmoji digitado pelo usuário aparece como um caractere placeholder (o sistema não consegue renderizar o glyph). Definir a propriedade habilita tanto a renderização quanto a aba “Genmoji” no teclado do sistema, para que o usuário possa criar Genmojis personalizados dentro do text view.
O TextField e o TextEditor nativos do SwiftUI não expõem atualmente um modificador supportsAdaptiveImageGlyph. Apps SwiftUI que precisam renderizar adaptive image glyphs envolvem o UITextView em um UIViewRepresentable e definem supportsAdaptiveImageGlyph = true na view subjacente. Wrappers da comunidade como GlyphMeThat fornecem essa ponte pronta para uso.
TextKit 2 é peça estrutural
NSAdaptiveImageGlyph exige a arquitetura de layout do TextKit 24. O TextKit 1 (a engine de texto legada que veio com o modelo original de NSTextStorage/NSLayoutManager/NSTextContainer) não renderiza adaptive image glyphs corretamente; o glyph aparece como um placeholder genérico ou simplesmente não é diagramado.
Apps em três estados:
Novos apps em iOS 18+. Adotam TextKit 2 por padrão. UITextView inicializado pelo Interface Builder ou por init(frame:textContainer:) usa TextKit 2 por padrão no iOS 16+. Código novo já recebe isso de graça.
Apps legados ainda em TextKit 1. É preciso migrar. A migração para TextKit 2 não é trivial em apps que fazem subclasse de NSLayoutManager, sobrescrevem métodos delegate relacionados a layout ou usam o NSTextStorage mais antigo diretamente. O guia de migração de TextKit da Apple cobre o caminho; para apps com uso simples de UITextView, a migração é, em sua maior parte, automática.
Apps híbridos. Alguns apps embutem WKWebView para edição em HTML junto com UITextView para edição simples. O WKWebView lida com adaptive image glyphs através do seu próprio caminho de renderização (não do TextKit), então um app híbrido pode ter uma superfície que suporta Genmoji e outra que não. Documente o comportamento; os usuários percebem quando um editor suporta emoji personalizado e o outro descarta.
Integração com NSAttributedString
Adaptive image glyphs trafegam por attributed strings via o atributo NSAttributedString.Key.adaptiveImageGlyph3:
import UIKit
// Construct an attributed string containing a single adaptive image glyph
let glyph: NSAdaptiveImageGlyph = ...
let attrString = NSAttributedString(
adaptiveImageGlyph: glyph,
attributes: [
.font: UIFont.systemFont(ofSize: 17)
]
)
// Concatenate with surrounding text
let composed = NSMutableAttributedString(string: "Look at this ")
composed.append(attrString)
composed.append(NSAttributedString(string: " I just made!"))
O padrão se compõe: um glyph dentro de texto, dentro de mais texto. O sistema cuida do layout (incluindo o dimensionamento adaptativo do glyph para a fonte do texto ao redor) automaticamente.
Para leitura, iterar pelo atributo .adaptiveImageGlyph de um NSAttributedString retorna instâncias de NSAdaptiveImageGlyph nas posições em que aparecem:
attributedString.enumerateAttribute(
.adaptiveImageGlyph,
in: NSRange(location: 0, length: attributedString.length)
) { value, range, _ in
if let glyph = value as? NSAdaptiveImageGlyph {
// process glyph + range
}
}
Apps que filtram, transformam ou persistem texto usam essa enumeração para encontrar glyphs e decidir o que fazer com eles.
Persistência e serialização
O armazenamento em texto puro (uma String, um arquivo UTF-8) não preserva adaptive image glyphs. O caractere placeholder Unicode que representa o glyph no texto atribuído é serializado como U+FFFC (object replacement) ou nada, e os dados reais do glyph se perdem.
Para uma persistência com round-trip, os apps precisam de um formato de texto rico5:
RTFD. Formato de texto rico + anexos da Apple. Faz round-trip com adaptive image glyphs. Usado pelo Notas, pelo Mail (ao enviar conteúdo rico) e pelo TextEdit. O formato é verboso (um bundle de diretório com anexos), mas sem perdas.
HTML com imagens embutidas. Amigável para a web. Os glyphs são serializados como tags <img> com data URIs codificadas em base64. Payloads maiores, mas funciona com a maior parte dos destinatários capazes de receber texto rico.
Markdown com extensões. O Markdown padrão não tem uma sintaxe para adaptive image glyph, mas dialetos estendidos (CommonMark com suporte a anexos, o Markdown estendido da própria Apple) podem carregá-los. Documente a exigência de dialeto para qualquer persistência baseada em markdown.
Apps que enviam texto pela rede (chat, email, redes sociais) precisam decidir: preservar os glyphs de ponta a ponta (só funciona se tanto remetente quanto destinatário estiverem em iOS 18+ e o transporte suportar texto rico), descartar os glyphs e substituir por um texto de fallback (contentDescription), ou renderizar o glyph como uma imagem do sistema e embutir a imagem. A escolha certa depende do público e da plataforma.
Falhas comuns
Três padrões vindos de logs de integração de Genmoji:
Esquecer supportsAdaptiveImageGlyph = true. O bug mais comum. O text view renderiza emojis Unicode normalmente, mas o Genmoji aparece como caracteres placeholder. Solução: defina a propriedade como true em todo UITextView/NSTextView que aceite texto digitado pelo usuário. Para SwiftUI, use o modificador .supportsAdaptiveImageGlyph(true).
Persistência em texto puro descartando glyphs. Salvar o conteúdo do text view como text (uma String simples) descarta o Genmoji. O usuário digita um emoji personalizado, vê no text view, salva o documento, reabre; o emoji sumiu. Solução: persista como attributedText em um formato de texto rico que suporte adaptive image glyphs (RTFD, HTML, formato customizado com canal lateral de anexos).
Transmissão em rede descartando glyphs silenciosamente. Um app de mensagens que serializa as mensagens enviadas como texto puro descarta o Genmoji no envio. O destinatário vê um caractere placeholder ou um espaço vazio. Solução: ou envie conteúdo rico (e garanta que o destinatário tenha suporte a ele) ou substitua pelo contentDescription para destinatários em texto puro e inclua os dados da imagem como anexo separado.
O que esse padrão significa para apps em iOS 18+
Três conclusões.
-
Defina
supportsAdaptiveImageGlyph = trueem toda entrada de texto. Apps que aceitam texto digitado pelo usuário precisam optar explicitamente por adaptive image glyphs. Essa única propriedade é a diferença entre o Genmoji renderizar e o Genmoji quebrar. -
Migre para TextKit 2 se você ainda está em TextKit 1. O TextKit 1 está em modo de manutenção. Os recursos da era do iOS 26 (adaptive image glyphs, reescrita inline do Writing Tools, renderização de texto com Liquid Glass) todos pressupõem TextKit 2. O custo da migração é real, mas a alternativa é entregar em uma engine de texto deprecada.
-
Escolha seu formato de persistência pensando em adaptive image glyphs. RTFD para armazenamento nativo no iOS; HTML com imagens embutidas para armazenamento compatível com a web; formato binário customizado com canal lateral de anexos para apps de alto desempenho. Texto puro é o padrão errado para apps em que os usuários vão digitar Genmoji.
O cluster Apple Ecosystem completo: App Intents tipados; servidores MCP; a questão do roteamento; Foundation Models; a distinção LLM runtime vs ferramental; três superfícies; o padrão de fonte única da verdade; Dois servidores MCP; hooks para desenvolvimento Apple; Live Activities; o contrato de runtime do watchOS; internals do SwiftUI; o modelo mental espacial do RealityKit; disciplina de schema com SwiftData; padrões de Liquid Glass; shipping multiplataforma; a matriz de plataformas; framework Vision; Symbol Effects; inferência com Core ML; API do Writing Tools; Swift Testing; Privacy Manifest; acessibilidade como plataforma; tipografia SF Pro; padrões espaciais do visionOS; framework Speech; migrações do SwiftData; focus engine do tvOS; internals do @Observable; protocolo Layout do SwiftUI; SF Symbols personalizados; AVFoundation HDR; ciclo de vida de workout no watchOS; App Intents 2.0 no iOS 26; API do Image Playground; sobre o que me recuso a escrever. O hub está em Apple Ecosystem Series. Para um contexto mais amplo de iOS-com-AI-agents, veja o guia de iOS Agent Development.
FAQ
Meu app já recebe o Genmoji “de graça” se eu só usar o UITextView?
Não exatamente. O padrão de UITextView.supportsAdaptiveImageGlyph é false. Os apps precisam optar definindo a propriedade como true. Uma vez habilitada, a aba Genmoji do teclado do sistema aparece para o usuário e o Genmoji colado é renderizado corretamente. Sem a opção habilitada, o Genmoji digitado em outro lugar e colado no text view aparece como caracteres placeholder.
Preciso ter o Apple Intelligence habilitado para testar Genmoji?
Para a criação completa de Genmoji, sim. O fluxo de criação de Genmoji voltado ao usuário exige hardware compatível com Apple Intelligence (iPhone 15 Pro em diante, Macs com chips da série M) com iOS 18+ e Apple Intelligence habilitado. Para testes de desenvolvimento da renderização de NSAdaptiveImageGlyph, você pode construir instâncias de glyph de teste programaticamente com dados de imagem de exemplo e verificar a renderização do text view em qualquer dispositivo ou simulador iOS 18+.
O que acontece com um Genmoji quando eu envio para alguém em iOS 17?
Sem um transporte de texto rico que preserve o glyph, o destinatário vê o contentDescription (texto alternativo) ou um caractere placeholder. Frameworks de mensagens modernos (o app Mensagens da Apple, versões recentes de clientes de email) lidam com o fallback automaticamente; protocolos customizados precisam de tratamento explícito.
Posso criar instâncias de NSAdaptiveImageGlyph programaticamente?
Sim. O inicializador público é init(imageContent: Data), recebendo dados HEIC adaptive-image previamente codificados. Os campos contentDescription, contentIdentifier e contentType são lidos a partir dos dados codificados, em vez de serem passados como argumentos separados; apps que criam adaptive image glyphs personalizados preparam o payload HEIC com os metadados embutidos e então constroem o glyph a partir desses dados. A sessão 10220 da WWDC 2024 (“Bring expression to your app with Genmoji”) cobre o fluxo completo de criação.
Como isso interage com o Writing Tools?
O Writing Tools (coberto em API do Writing Tools) preserva adaptive image glyphs nas saídas de reescrita. Um usuário que seleciona um texto contendo Genmoji e pede ao Writing Tools que reescreva recebe uma reescrita que preserva o Genmoji em posições semanticamente apropriadas. Apps que participam do Writing Tools via UIWritingToolsCoordinator precisam fazer o round-trip das instâncias de NSAdaptiveImageGlyph corretamente através do seu armazenamento de texto customizado.
Qual é a diferença entre NSAdaptiveImageGlyph e NSTextAttachment?
NSTextAttachment é o sistema de anexos mais antigo e mais amplo, para conteúdo inline não textual (imagens, arquivos, desenhos personalizados) em texto atribuído. NSAdaptiveImageGlyph é a especialização do iOS 18 para imagens inline parecidas com emoji, que se adaptam às características da fonte ao redor. Os dois são anexados via atributos de attributed string, mas usam chaves diferentes (.attachment vs .adaptiveImageGlyph) e caminhos de renderização diferentes (TextKit 1+TextKit 2 vs apenas TextKit 2). Código novo voltado a conteúdo no estilo Genmoji usa NSAdaptiveImageGlyph.
Referências
-
Documentação para desenvolvedores Apple:
supportsAdaptiveImageGlyph. A propriedade de opt-in declarada no protocoloUITextInputao qualUITextViewadere; a mesma propriedade é, portanto, acessível comotextView.supportsAdaptiveImageGlyph. ↩↩ -
Documentação para desenvolvedores Apple:
NSAdaptiveImageGlyph. O tipo de dado que encapsula o conteúdo da imagem, identificador, descrição e tipo de conteúdo. ↩↩ -
Documentação para desenvolvedores Apple:
NSAttributedString.Key.adaptiveImageGlypheNSAttributedString(adaptiveImageGlyph:attributes:). A superfície de integração de attributed string para adaptive image glyphs. ↩↩ -
Documentação para desenvolvedores Apple: Guia de migração para TextKit 2. O caminho de migração da engine de layout legada do TextKit 1 para o TextKit 2, exigida para a renderização de adaptive image glyphs. ↩
-
Documentação para desenvolvedores Apple:
NSAttributedString.DocumentType. Os formatos de texto rico suportados (RTFD, HTML, etc.) para o round-trip de adaptive image glyphs através da persistência. ↩