Genmoji et NSAdaptiveImageGlyph : emoji intégrés sur iOS 18+
Genmoji est le nom destiné à l’utilisateur de la fonctionnalité d’emoji personnalisés d’Apple Intelligence : l’utilisateur saisit une description, le système génère une image inline de type emoji, et le résultat apparaît dans le texte aux côtés des emoji Unicode. La surface destinée aux développeurs est NSAdaptiveImageGlyph, une classe iOS 18+ qui représente des images adaptatives inline dans le texte attribué1. Genmoji est l’une des sources d’instances de NSAdaptiveImageGlyph ; les apps qui manipulent du texte attribué doivent prendre en charge cette classe pour afficher Genmoji (ainsi que tout futur contenu de type adaptive-image-glyph qu’Apple introduira).
TL;DR
NSAdaptiveImageGlyph(iOS 18+) est un type de données qui encapsule une image adaptative ainsi que des métadonnées d’identification. Les saisies Genmoji depuis le clavier système arrivent sous forme d’instances deNSAdaptiveImageGlyphintégrées dans le texte attribué2.supportsAdaptiveImageGlyphest déclarée sur le protocoleUITextInput;UITextViews’y conforme, donc la propriété est accessible en écriture viatextView.supportsAdaptiveImageGlyph = true. La discussion d’Apple est directe : lorsque la propriété estfalse, « le système d’entrée n’autorise pas la saisie textuelle à contenir des images adaptatives ». Les apps doivent opter explicitement pour que Genmoji s’affiche.- Les glyphes d’image adaptatifs nécessitent TextKit 2. Les apps encore sur TextKit 1 ne rendent pas correctement les
NSAdaptiveImageGlyph. Les nouvelles apps ciblant iOS 18+ devraient utiliser TextKit 2 par défaut. NSAttributedStringtransporte les glyphes d’image adaptatifs via l’attributNSAttributedString.Key.adaptiveImageGlyph. L’initialiseurNSAttributedString(adaptiveImageGlyph:attributes:)construit une chaîne attribuée contenant un seul glyphe3.- La persistance et l’aller-retour exigent de la rigueur. Le stockage en texte brut supprime entièrement les Genmoji ; les formats de texte enrichi (RTFD, Markdown avec extensions, HTML avec données d’image intégrées) les préservent.
Ce que transporte NSAdaptiveImageGlyph
Un NSAdaptiveImageGlyph est un wrapper de données avec quatre propriétés d’identification2 :
imageContent: Data. Les données d’image proprement dites, dans le format déclaré parcontentType.contentIdentifier: String. Un identifiant unique pour l’instance du glyphe. Utilisé pour la déduplication et pour le cache interne du système.contentDescription: String. Le texte alternatif décrivant le glyphe. Les apps qui exposent des étiquettes d’accessibilité ou qui envoient des glyphes à des destinataires ne prenant pas en charge les glyphes utilisent cette propriété.contentType: UTType. Une propriété de type au niveau de la classe exposant le format d’image qu’Apple utilise pour les glyphes adaptatifs (une variante HEIC). Les apps qui sérialisent consultent cette propriété pour orienter un traitement adapté au format.
Les données représentent généralement quelques dizaines de kilo-octets pour un Genmoji standard. Plusieurs tailles sont encodées dans le même fichier image en utilisant les fonctionnalités d’image adaptative de HEIC ; le système choisit la bonne taille en fonction du contexte de rendu.
Activer les glyphes d’image adaptatifs dans UITextView
L’opt-in tient en une seule propriété1 :
import UIKit
let textView = UITextView()
textView.supportsAdaptiveImageGlyph = true
// TextKit 2 is required; modern UITextView usage gets it by default
// (see: developer.apple.com/documentation/uikit/using-textkit-2-to-interact-with-text)
Sans supportsAdaptiveImageGlyph = true, les Genmoji saisis par l’utilisateur apparaissent comme des caractères de remplacement (le système ne peut pas rendre le glyphe). Définir la propriété active à la fois le rendu et l’onglet « Genmoji » du clavier système, afin que l’utilisateur puisse créer des Genmoji personnalisés au sein de la zone de texte.
Les TextField et TextEditor natifs de SwiftUI n’exposent pas actuellement de modificateur supportsAdaptiveImageGlyph. Les apps SwiftUI qui ont besoin du rendu des glyphes d’image adaptatifs encapsulent UITextView dans un UIViewRepresentable et définissent supportsAdaptiveImageGlyph = true sur la vue sous-jacente. Des wrappers communautaires comme GlyphMeThat fournissent ce pont prêt à l’emploi.
TextKit 2 est porteur
NSAdaptiveImageGlyph requiert l’architecture de mise en page de TextKit 24. TextKit 1 (le moteur de texte hérité livré avec le modèle d’origine NSTextStorage/NSLayoutManager/NSTextContainer) ne rend pas correctement les glyphes d’image adaptatifs ; le glyphe apparaît comme un placeholder générique ou échoue complètement à se mettre en page.
Trois cas d’apps :
Nouvelles apps sur iOS 18+. TextKit 2 par défaut. Un UITextView initialisé via Interface Builder ou init(frame:textContainer:) utilise TextKit 2 par défaut depuis iOS 16+4. Le code récent en bénéficie sans effort.
Apps héritées encore sur TextKit 1. Une migration est requise. La migration vers TextKit 2 n’est pas triviale pour les apps qui sous-classent NSLayoutManager, qui surchargent des méthodes de délégation liées à la mise en page, ou qui utilisent directement l’ancien NSTextStorage. La documentation TextKit 2 d’Apple couvre l’architecture de mise en page moderne ; pour les apps avec un usage simple de UITextView, la migration est en grande partie automatique.
Apps hybrides. Certaines apps embarquent WKWebView pour l’édition HTML aux côtés de UITextView pour l’édition simple. WKWebView gère les glyphes d’image adaptatifs via son propre chemin de rendu (et non TextKit), de sorte qu’une app hybride peut avoir une surface qui prend en charge Genmoji et une autre qui ne le fait pas. Documentez ce comportement ; les utilisateurs remarquent quand un éditeur prend en charge les emoji personnalisés et que l’autre les supprime.
Intégration avec NSAttributedString
Les glyphes d’image adaptatifs circulent dans les chaînes attribuées via l’attribut 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!"))
Le motif se compose : un glyphe à l’intérieur du texte, lui-même à l’intérieur d’un texte plus large. Le système gère automatiquement la mise en page (y compris le dimensionnement adaptatif du glyphe par rapport à la police du texte environnant).
Pour la lecture, l’itération sur l’attribut .adaptiveImageGlyph d’un NSAttributedString retourne les instances NSAdaptiveImageGlyph aux positions où elles apparaissent :
attributedString.enumerateAttribute(
.adaptiveImageGlyph,
in: NSRange(location: 0, length: attributedString.length)
) { value, range, _ in
if let glyph = value as? NSAdaptiveImageGlyph {
// process glyph + range
}
}
Les apps qui filtrent, transforment ou persistent du texte utilisent cette énumération pour repérer les glyphes et décider de leur traitement.
Persistance et sérialisation
Le stockage en texte brut (un String, un fichier UTF-8) ne préserve pas les glyphes d’image adaptatifs. Le caractère placeholder Unicode qui représente le glyphe dans le texte attribué est sérialisé en U+FFFC (object replacement) ou rien du tout, et les données réelles du glyphe sont perdues.
Pour une persistance avec aller-retour, les apps ont besoin d’un format de texte enrichi5 :
RTFD. Le format texte enrichi + pièces jointes d’Apple. Préserve les glyphes d’image adaptatifs lors d’un aller-retour. Utilisé par Notes, Mail (lors de l’envoi de contenu enrichi) et TextEdit. Le format est verbeux (un bundle de répertoire avec des pièces jointes) mais sans perte.
HTML avec images intégrées. Adapté au web. Les glyphes se sérialisent en balises <img> avec des URI de données encodés en base64. Charges utiles plus volumineuses, mais fonctionne avec la plupart des destinataires capables de traiter du texte enrichi.
Markdown avec extensions. Le Markdown standard n’a pas de syntaxe pour les glyphes d’image adaptatifs, mais les dialectes étendus (CommonMark avec prise en charge des pièces jointes, le Markdown étendu propre à Apple) peuvent les transporter. Documentez l’exigence de dialecte pour toute persistance basée sur Markdown.
Les apps qui envoient du texte sur le réseau (chat, e-mail, réseaux sociaux) doivent décider : préserver les glyphes de bout en bout (ne fonctionne que si l’expéditeur et le destinataire sont tous deux sur iOS 18+ et que le transport prend en charge le texte enrichi), supprimer les glyphes et substituer un texte de repli (contentDescription), ou rendre le glyphe sous forme d’image système et intégrer cette image. Le bon choix dépend du public et de la plateforme.
Échecs courants
Trois modes d’échec reviennent dans l’adoption de NSAdaptiveImageGlyph :
Oublier supportsAdaptiveImageGlyph = true. Le bug le plus fréquent. La zone de texte rend correctement les emoji Unicode mais Genmoji apparaît comme des caractères placeholder. Correctif : définissez la propriété à true sur chaque UITextView (UIKit) ou tout conformeur NSTextInputClient tel que NSTextView (AppKit). Pour SwiftUI, aucun modificateur natif n’existe ; encapsulez un UITextView dans un UIViewRepresentable (ou NSViewRepresentable sur macOS) et définissez la propriété sur la vue sous-jacente.
Persistance en texte brut qui supprime les glyphes. Sauvegarder le contenu de la zone de texte en tant que text (String brut) écarte les Genmoji. L’utilisateur saisit un emoji personnalisé, le voit dans la zone de texte, sauvegarde le document, le rouvre ; l’emoji a disparu. Correctif : persistez via attributedText avec un format de texte enrichi qui prend en charge les glyphes d’image adaptatifs (RTFD, HTML, format personnalisé avec canal latéral pour pièces jointes).
Transmission réseau qui perd silencieusement les glyphes. Une app de messagerie qui sérialise les messages sortants en texte brut supprime les Genmoji à l’envoi. Le destinataire voit un caractère placeholder ou un espace vide. Correctif : envoyez du contenu enrichi (et assurez-vous que le destinataire le prend en charge) ou substituez le contentDescription pour les destinataires en texte brut et incluez les données d’image en pièce jointe séparée.
Ce que ce schéma signifie pour les apps iOS 18+
Trois enseignements.
-
Définissez
supportsAdaptiveImageGlyph = truesur chaque saisie de texte. Les apps qui acceptent du texte saisi par l’utilisateur s’inscrivent par défaut pour les glyphes d’image adaptatifs. Cette unique propriété fait la différence entre un Genmoji qui s’affiche et un Genmoji qui casse. -
Migrez vers TextKit 2 si vous êtes encore sur TextKit 1. TextKit 1 est en mode maintenance. Les nouvelles fonctionnalités de l’ère iOS 26 (glyphes d’image adaptatifs, réécriture inline de Writing Tools, rendu de texte Liquid Glass) supposent toutes TextKit 2. Le coût de migration est réel, mais l’alternative est de livrer dans un moteur de texte déprécié.
-
Choisissez votre format de persistance en gardant les glyphes d’image adaptatifs à l’esprit. RTFD pour le stockage iOS natif ; HTML avec images intégrées pour le stockage compatible web ; format binaire personnalisé avec canal latéral pour pièces jointes pour les apps à hautes performances. Le texte brut est le mauvais choix par défaut pour les apps où les utilisateurs saisiront des Genmoji.
L’ensemble du cluster Apple Ecosystem : Writing Tools pour la surface texte parallèle d’Apple Intelligence ; Image Playground pour la génération d’images ; App Intents 2.0 pour l’intégration Apple Intelligence d’iOS 26 ; Foundation Models pour le LLM embarqué. Le hub se trouve sur la série Apple Ecosystem. Pour un contexte plus large iOS-avec-agents-IA, consultez le guide iOS Agent Development.
FAQ
Mon app obtient-elle Genmoji « gratuitement » si j’utilise simplement UITextView ?
Pas tout à fait. La valeur par défaut de UITextView.supportsAdaptiveImageGlyph est false. Les apps doivent opter explicitement en définissant la propriété à true. Une fois activé, l’onglet Genmoji du clavier système apparaît pour l’utilisateur, et les Genmoji collés s’affichent correctement. Sans cet opt-in, les Genmoji saisis ailleurs et collés dans la zone de texte apparaissent comme des caractères placeholder.
Ai-je besoin qu’Apple Intelligence soit activé pour tester Genmoji ?
Pour la création complète de Genmoji, oui. Le flux de création de Genmoji destiné à l’utilisateur nécessite un matériel compatible Apple Intelligence (iPhone 15 Pro et ultérieur, Mac à puce M) avec iOS 18+ et Apple Intelligence activé. Pour les tests de développement du rendu de NSAdaptiveImageGlyph, vous pouvez construire programmatiquement des instances de glyphes de test avec des données d’image d’exemple et vérifier le rendu de la zone de texte sur n’importe quel appareil ou simulateur iOS 18+.
Que devient un Genmoji lorsque je l’envoie à quelqu’un sous iOS 17 ?
Sans transport en texte enrichi qui préserve le glyphe, le destinataire voit le contentDescription (texte alternatif) ou un caractère placeholder. Les frameworks de messagerie modernes (l’app Messages d’Apple, les versions récentes des clients mail) gèrent automatiquement le repli ; les protocoles personnalisés nécessitent une gestion explicite.
Puis-je créer des instances de NSAdaptiveImageGlyph programmatiquement ?
Oui. L’initialiseur public est init(imageContent: Data), qui prend des données d’image adaptative HEIC pré-encodées. contentIdentifier et contentDescription sont des propriétés d’instance lues depuis la charge utile encodée ; contentType est un UTType au niveau de la classe décrivant le format qu’Apple utilise pour les glyphes adaptatifs (une variante HEIC) et n’est pas spécifique à l’instance. Les apps qui créent des glyphes d’image adaptatifs personnalisés préparent la charge utile HEIC avec l’identifiant et la description spécifiques au glyphe intégrés, puis construisent le glyphe à partir de ces données. La session WWDC 2024 10220 (« Bring expression to your app with Genmoji ») couvre l’intégralité du flux de création.
Comment cela interagit-il avec Writing Tools ?
Writing Tools (couvert dans Writing Tools API) préserve les glyphes d’image adaptatifs dans ses sorties de réécriture. Un utilisateur qui sélectionne un texte contenant des Genmoji et demande à Writing Tools de réécrire obtient une réécriture qui préserve les Genmoji aux positions sémantiquement appropriées. Les apps qui participent à Writing Tools via UIWritingToolsCoordinator doivent transporter correctement les instances de NSAdaptiveImageGlyph lors de l’aller-retour avec leur stockage de texte personnalisé.
Quelle est la différence entre NSAdaptiveImageGlyph et NSTextAttachment ?
NSTextAttachment est le système de pièces jointes plus ancien et plus large pour le contenu non textuel inline (images, fichiers, dessins personnalisés) dans le texte attribué. NSAdaptiveImageGlyph est la spécialisation iOS 18 pour les images inline de type emoji qui s’adaptent aux caractéristiques de la police environnante. Les deux sont attachés via les attributs de chaîne attribuée mais utilisent des clés différentes (.attachment contre .adaptiveImageGlyph) et des chemins de rendu différents (TextKit 1+TextKit 2 contre TextKit 2 uniquement). Le code récent ciblant le contenu de type Genmoji utilise NSAdaptiveImageGlyph.
Références
-
Documentation Apple Developer :
supportsAdaptiveImageGlyph. La propriété d’opt-in déclarée sur le protocoleUITextInputauquelUITextViewse conforme ; la même propriété est donc accessible viatextView.supportsAdaptiveImageGlyph. ↩↩ -
Documentation Apple Developer :
NSAdaptiveImageGlyph. Le type de données qui encapsule le contenu de l’image, l’identifiant, la description et le type de contenu. ↩↩ -
Documentation Apple Developer :
NSAttributedString.Key.adaptiveImageGlyphetNSAttributedString(adaptiveImageGlyph:attributes:). La surface d’intégration dans la chaîne attribuée pour les glyphes d’image adaptatifs. ↩↩ -
Documentation Apple Developer : TextKit et Using TextKit 2 to interact with text. Les points d’entrée actuels de TextKit 2 ; le rendu des glyphes d’image adaptatifs dépend de l’architecture de mise en page de TextKit 2. ↩↩
-
Documentation Apple Developer :
NSAttributedString.DocumentType. Les formats de texte enrichi pris en charge (RTFD, HTML, etc.) pour l’aller-retour des glyphes d’image adaptatifs lors de la persistance. ↩