Genmoji y NSAdaptiveImageGlyph: cómo las apps muestran emoji en línea generados por el usuario
Genmoji es el nombre de cara al usuario para la función de emoji personalizado de Apple Intelligence: el usuario escribe una descripción, el sistema genera una imagen tipo emoji en línea, y el resultado aparece en el texto junto con los emoji Unicode. La superficie de cara al desarrollador es NSAdaptiveImageGlyph, una clase de iOS 18+ que representa imágenes adaptativas en línea en texto con atributos1. Genmoji es una de las fuentes de instancias de NSAdaptiveImageGlyph; las apps que manejan texto con atributos necesitan dar soporte a la clase para mostrar Genmoji (y cualquier futuro contenido de adaptive-image-glyph que Apple introduzca).
La publicación recorre el API contrastándolo con la documentación de Apple. El enfoque es “qué debe hacer una app existente que maneja texto para mostrar Genmoji correctamente”, porque la mayoría de las apps que aceptan texto introducido por el usuario en un UITextView necesitan optar por los adaptive image glyphs para renderizar siquiera el Genmoji del usuario, y el lado de la persistencia tiene implicaciones de serialización que se pasan por alto.
TL;DR
NSAdaptiveImageGlyph(iOS 18+) es un tipo de dato que envuelve una imagen adaptativa junto con metadatos de identificación. La entrada de Genmoji desde el teclado del sistema llega como instancias deNSAdaptiveImageGlyphincrustadas en texto con atributos2.supportsAdaptiveImageGlyphse declara en el protocoloUITextInput;UITextViewse conforma a él, por lo que la propiedad es asignable comotextView.supportsAdaptiveImageGlyph = true. El valor por defecto esfalse; sin la opción activa, los Genmoji escritos por el usuario no se renderizan.- Los adaptive image glyphs requieren TextKit 2. Las apps que aún usan TextKit 1 no renderizan
NSAdaptiveImageGlyphcorrectamente. Las apps nuevas dirigidas a iOS 18+ deberían usar TextKit 2 por defecto. NSAttributedStringtransporta los adaptive image glyphs mediante el atributoNSAttributedString.Key.adaptiveImageGlyph. El inicializadorNSAttributedString(adaptiveImageGlyph:attributes:)construye una cadena con atributos que contiene un único glyph3.- La persistencia y el round-tripping requieren cuidado. El almacenamiento en texto plano elimina por completo los Genmoji; los formatos de texto enriquecido (RTFD, Markdown con extensiones, HTML con datos de imagen incrustados) los preservan.
Qué transporta NSAdaptiveImageGlyph
Un NSAdaptiveImageGlyph es un envoltorio de datos con cuatro propiedades de identificación2:
imageContent: Data. Los datos de la imagen en sí, en el formato declarado porcontentType.contentIdentifier: String. Un identificador único para la instancia del glyph. Se usa para deduplicación y para el caché interno del sistema.contentDescription: String. Texto alternativo que describe el glyph. Las apps que exponen etiquetas de accesibilidad o que envían glyphs a destinatarios que no los soportan usan esto.contentType: UTType. Una propiedad de tipo a nivel de clase que expone el formato de imagen que Apple usa para los adaptive glyphs (una variante de HEIC). Las apps que serializan revisan esto para impulsar un manejo consciente del formato.
Los datos suelen pesar decenas de kilobytes para un Genmoji estándar. Múltiples tamaños se codifican en el mismo archivo de imagen mediante las funciones de imagen adaptativa de HEIC; el sistema escoge el tamaño correcto según el contexto de renderizado.
Habilitar adaptive image glyphs en UITextView
La opción se activa con una sola propiedad1:
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)
Sin supportsAdaptiveImageGlyph = true, el Genmoji escrito por el usuario aparece como un carácter de marcador de posición (el sistema no puede renderizar el glyph). Configurar la propiedad habilita tanto el renderizado como la pestaña “Genmoji” del teclado del sistema, para que el usuario pueda crear Genmoji personalizados dentro de la vista de texto.
Los TextField y TextEditor nativos de SwiftUI no exponen actualmente un modificador supportsAdaptiveImageGlyph. Las apps en SwiftUI que necesitan renderizado de adaptive image glyphs envuelven UITextView en un UIViewRepresentable y configuran supportsAdaptiveImageGlyph = true en la vista subyacente. Wrappers de la comunidad como GlyphMeThat ofrecen este puente listo para usar.
TextKit 2 es estructural
NSAdaptiveImageGlyph requiere la arquitectura de layout de TextKit 24. TextKit 1 (el motor de texto heredado que se entregó con el modelo original de NSTextStorage/NSLayoutManager/NSTextContainer) no renderiza correctamente los adaptive image glyphs; el glyph aparece como un marcador de posición genérico o no logra siquiera maquetarse.
Las apps se encuentran en tres estados:
Apps nuevas en iOS 18+. TextKit 2 por defecto. UITextView inicializado mediante Interface Builder o init(frame:textContainer:) usa TextKit 2 por defecto en iOS 16+. El código nuevo lo obtiene gratis.
Apps heredadas que aún usan TextKit 1. Se requiere una migración. La migración a TextKit 2 no es trivial para apps que crean subclases de NSLayoutManager, sobrescriben métodos delegados relacionados con el layout, o usan directamente el antiguo NSTextStorage. La guía de migración de TextKit de Apple cubre el camino; para apps con un uso simple de UITextView, la migración es mayormente automática.
Apps híbridas. Algunas apps incrustan WKWebView para edición de HTML junto con UITextView para edición simple. WKWebView maneja los adaptive image glyphs a través de su propio camino de renderizado (no TextKit), por lo que una app híbrida puede tener una superficie que soporta Genmoji y otra que no. Documenta el comportamiento; los usuarios notan cuando un editor soporta emoji personalizados y el otro los elimina.
Integración con NSAttributedString
Los adaptive image glyphs fluyen a través de las cadenas con atributos mediante el 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!"))
El patrón se compone: un glyph dentro de texto dentro de más texto. El sistema gestiona el layout (incluyendo el dimensionamiento adaptativo del glyph respecto a la fuente del texto que lo rodea) automáticamente.
Para la lectura, iterar sobre el atributo .adaptiveImageGlyph de un NSAttributedString devuelve instancias de NSAdaptiveImageGlyph en las posiciones donde aparecen:
attributedString.enumerateAttribute(
.adaptiveImageGlyph,
in: NSRange(location: 0, length: attributedString.length)
) { value, range, _ in
if let glyph = value as? NSAdaptiveImageGlyph {
// process glyph + range
}
}
Las apps que filtran, transforman o persisten texto usan esta enumeración para encontrar glyphs y decidir qué hacer con ellos.
Persistencia y serialización
El almacenamiento en texto plano (un String, un archivo UTF-8) no preserva los adaptive image glyphs. El carácter de marcador de posición Unicode que representa el glyph en el texto con atributos se serializa como U+FFFC (object replacement) o como nada, y los datos reales del glyph se pierden.
Para una persistencia con round-trip, las apps necesitan un formato de texto enriquecido5:
RTFD. El formato de texto enriquecido + adjuntos de Apple. Hace round-trip de los adaptive image glyphs. Lo usan Notas, Mail (cuando envía contenido enriquecido) y TextEdit. El formato es verboso (un bundle de directorio con adjuntos) pero sin pérdidas.
HTML con imágenes incrustadas. Compatible con la web. Los glyphs se serializan como etiquetas <img> con URIs de datos codificados en base64. Cargas más grandes pero funciona en la mayoría de los receptores capaces de procesar texto enriquecido.
Markdown con extensiones. El Markdown estándar no tiene una sintaxis para adaptive image glyphs, pero los dialectos extendidos (CommonMark con soporte para adjuntos, el propio Markdown extendido de Apple) pueden transportarlos. Documenta el requisito de dialecto para cualquier persistencia basada en markdown.
Las apps que envían texto a través de la red (chat, correo, redes sociales) deben decidir: preservar los glyphs de extremo a extremo (solo funciona si tanto el emisor como el receptor están en iOS 18+ y el transporte soporta texto enriquecido), eliminar los glyphs y sustituir por texto alternativo (contentDescription), o renderizar el glyph como una imagen del sistema e incrustar la imagen. La elección correcta depende de la audiencia y la plataforma.
Fallos comunes
Tres patrones que aparecen en los registros de integración de Genmoji:
Olvidar supportsAdaptiveImageGlyph = true. El bug más común. La vista de texto renderiza bien los emoji Unicode pero los Genmoji aparecen como caracteres de marcador de posición. Solución: configura la propiedad como true en cada UITextView/NSTextView que acepte texto introducido por el usuario. Para SwiftUI, usa el modificador .supportsAdaptiveImageGlyph(true).
Persistencia en texto plano que elimina los glyphs. Guardar el contenido de la vista de texto como text (un String plano) descarta los Genmoji. El usuario escribe un emoji personalizado, lo ve en la vista de texto, guarda el documento, lo reabre; el emoji ha desaparecido. Solución: persiste como attributedText con un formato de texto enriquecido que soporte adaptive image glyphs (RTFD, HTML, formato personalizado con canal lateral de adjuntos).
Transmisión por red que elimina silenciosamente los glyphs. Una app de mensajería que serializa los mensajes salientes como texto plano elimina los Genmoji al enviarlos. El destinatario ve un carácter de marcador de posición o un espacio vacío. Solución: o bien envía contenido enriquecido (asegurándote de que el destinatario lo soporte) o sustituye con contentDescription para receptores en texto plano e incluye los datos de la imagen como un adjunto separado.
Qué significa este patrón para las apps de iOS 18+
Tres conclusiones.
-
Configura
supportsAdaptiveImageGlyph = trueen cada entrada de texto. Las apps que aceptan texto introducido por el usuario deberían optar por los adaptive image glyphs por defecto. Esa única propiedad es la diferencia entre que Genmoji se renderice o se rompa. -
Migra a TextKit 2 si aún estás en TextKit 1. TextKit 1 está en modo de mantenimiento. Las nuevas funciones de la era iOS 26 (adaptive image glyphs, la reescritura en línea de Writing Tools, el renderizado de texto de Liquid Glass) asumen todas TextKit 2. El costo de migración es real, pero la alternativa es entregar en un motor de texto deprecado.
-
Elige tu formato de persistencia teniendo en cuenta los adaptive image glyphs. RTFD para almacenamiento nativo de iOS; HTML con imágenes incrustadas para almacenamiento compatible con la web; formato binario personalizado con canal lateral de adjuntos para apps de alto rendimiento. El texto plano es el valor por defecto incorrecto para apps en las que los usuarios escribirán Genmoji.
El cluster completo de Apple Ecosystem: App Intents tipados; servidores MCP; la pregunta del enrutamiento; Foundation Models; la distinción LLM entre runtime y tooling; tres superficies; el patrón de fuente única de verdad; Two MCP Servers; hooks para desarrollo en Apple; Live Activities; el contrato de runtime de watchOS; internals de SwiftUI; el modelo mental espacial de RealityKit; disciplina de esquemas en SwiftData; patrones de Liquid Glass; entrega multiplataforma; la matriz de plataformas; el framework Vision; Symbol Effects; inferencia con Core ML; API de Writing Tools; Swift Testing; Privacy Manifest; accesibilidad como plataforma; tipografía SF Pro; patrones espaciales de visionOS; el framework Speech; migraciones en SwiftData; el motor de foco de tvOS; internals de @Observable; el protocolo Layout de SwiftUI; SF Symbols personalizados; AVFoundation HDR; ciclo de vida de entrenamientos en watchOS; App Intents 2.0 en iOS 26; API de Image Playground; sobre qué me niego a escribir. El hub está en la serie Apple Ecosystem. Para un contexto más amplio sobre iOS con agentes de IA, consulta la guía de iOS Agent Development.
FAQ
¿Mi app obtiene Genmoji “gratis” si solo uso UITextView?
No del todo. El valor por defecto de UITextView.supportsAdaptiveImageGlyph es false. Las apps deben optar configurando la propiedad como true. Una vez habilitada, la pestaña Genmoji del teclado del sistema aparece para el usuario, y los Genmoji pegados se renderizan correctamente. Sin la opción activa, los Genmoji escritos en otra parte y pegados en la vista de texto aparecen como caracteres de marcador de posición.
¿Necesito tener Apple Intelligence habilitado para probar Genmoji?
Para la creación completa de Genmoji, sí. El flujo de creación de Genmoji de cara al usuario requiere hardware compatible con Apple Intelligence (iPhone 15 Pro y posteriores, Macs con chips de la serie M) con iOS 18+ y Apple Intelligence habilitado. Para pruebas de desarrollo del renderizado de NSAdaptiveImageGlyph, puedes construir instancias de glyph de prueba programáticamente con datos de imagen de muestra y verificar el renderizado de la vista de texto en cualquier dispositivo o simulador con iOS 18+.
¿Qué pasa con un Genmoji cuando lo envío a alguien que usa iOS 17?
Sin un transporte de texto enriquecido que preserve el glyph, el destinatario ve el contentDescription (texto alternativo) o un carácter de marcador de posición. Los frameworks de mensajería modernos (la app Mensajes de Apple, las versiones recientes de los clientes de correo) manejan automáticamente el fallback; los protocolos personalizados necesitan un manejo explícito.
¿Puedo crear instancias de NSAdaptiveImageGlyph programáticamente?
Sí. El inicializador público es init(imageContent: Data), que toma datos HEIC de imagen adaptativa precodificados. contentDescription, contentIdentifier y contentType se leen de los datos codificados en lugar de pasarse como argumentos separados; las apps que crean adaptive image glyphs personalizados preparan la carga HEIC con los metadatos incrustados, y luego construyen el glyph a partir de esos datos. La sesión 10220 de la WWDC 2024 (“Bring expression to your app with Genmoji”) cubre el flujo de creación completo.
¿Cómo interactúa esto con Writing Tools?
Writing Tools (cubierto en API de Writing Tools) preserva los adaptive image glyphs en sus salidas reescritas. Un usuario que selecciona texto que contiene Genmoji y le pide a Writing Tools que lo reescriba obtiene una reescritura que preserva los Genmoji en posiciones semánticamente apropiadas. Las apps que participan en Writing Tools a través de UIWritingToolsCoordinator necesitan hacer round-trip correctamente con las instancias de NSAdaptiveImageGlyph a través de su almacenamiento de texto personalizado.
¿Cuál es la diferencia entre NSAdaptiveImageGlyph y NSTextAttachment?
NSTextAttachment es el sistema de adjuntos más antiguo y amplio para contenido en línea no textual (imágenes, archivos, dibujos personalizados) en texto con atributos. NSAdaptiveImageGlyph es la especialización de iOS 18 para imágenes en línea tipo emoji que se adaptan a las características de la fuente que las rodea. Ambos se adjuntan mediante atributos de cadena con atributos pero usan claves diferentes (.attachment vs .adaptiveImageGlyph) y caminos de renderizado diferentes (TextKit 1+TextKit 2 vs solo TextKit 2). El código nuevo dirigido a contenido tipo Genmoji usa NSAdaptiveImageGlyph.
Referencias
-
Documentación para desarrolladores de Apple:
supportsAdaptiveImageGlyph. La propiedad de opt-in declarada en el protocoloUITextInputal que se conformaUITextView; por lo tanto, la misma propiedad es accesible comotextView.supportsAdaptiveImageGlyph. ↩↩ -
Documentación para desarrolladores de Apple:
NSAdaptiveImageGlyph. El tipo de dato que envuelve el contenido de la imagen, el identificador, la descripción y el tipo de contenido. ↩↩ -
Documentación para desarrolladores de Apple:
NSAttributedString.Key.adaptiveImageGlyphyNSAttributedString(adaptiveImageGlyph:attributes:). La superficie de integración con cadenas con atributos para los adaptive image glyphs. ↩↩ -
Documentación para desarrolladores de Apple: guía de migración a TextKit 2. El camino de migración del motor de layout heredado de TextKit 1 a TextKit 2, requerido para el renderizado de adaptive image glyphs. ↩
-
Documentación para desarrolladores de Apple:
NSAttributedString.DocumentType. Los formatos de texto enriquecido soportados (RTFD, HTML, etc.) para hacer round-trip de los adaptive image glyphs a través de la persistencia. ↩