Genmoji et NSAdaptiveImageGlyph : comment les apps affichent les emojis intégrés générés par l'utilisateur
Genmoji est le nom destiné à l’utilisateur de la fonctionnalité d’emoji personnalisé d’Apple Intelligence : l’utilisateur saisit une description, le système génère une image intégrée de type emoji, et le résultat apparaît dans le texte aux côtés des emojis Unicode. La surface destinée aux développeurs est NSAdaptiveImageGlyph, une classe iOS 18+ qui représente des images intégrées adaptatives dans le texte attribué1. Genmoji est l’une des sources d’instances NSAdaptiveImageGlyph ; les apps qui gèrent du texte attribué doivent prendre en charge cette classe pour afficher les Genmoji (et tout futur contenu de type adaptive-image-glyph qu’Apple introduira).
Cet article parcourt l’API en regard de la documentation Apple. Le cadrage est « ce qu’une app de gestion de texte existante doit faire pour afficher Genmoji correctement », car la plupart des apps qui acceptent du texte saisi par l’utilisateur dans une UITextView doivent activer les adaptive image glyphs pour pouvoir afficher les Genmoji de l’utilisateur, et le côté persistance comporte des implications de sérialisation qui passent souvent inaperçues.
TL;DR
NSAdaptiveImageGlyph(iOS 18+) est un type de données qui encapsule une image adaptative ainsi que des métadonnées d’identification. La saisie Genmoji depuis le clavier système arrive sous forme d’instancesNSAdaptiveImageGlyphintégrées dans le texte attribué2.supportsAdaptiveImageGlyphest déclarée sur le protocoleUITextInput;UITextViews’y conforme, donc la propriété est définissable viatextView.supportsAdaptiveImageGlyph = true. La valeur par défaut estfalse; sans activation, les Genmoji saisis par l’utilisateur ne s’affichent pas.- Les adaptive image glyphs nécessitent TextKit 2. Les apps encore sous TextKit 1 n’affichent pas correctement
NSAdaptiveImageGlyph. Les nouvelles apps ciblant iOS 18+ doivent utiliser TextKit 2 par défaut. NSAttributedStringtransporte les adaptive image glyphs 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 des précautions. 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 NSAdaptiveImageGlyph transporte
Un NSAdaptiveImageGlyph est un wrapper de données comportant quatre propriétés d’identification2 :
imageContent: Data. Les données d’image elles-mêmes, 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. Texte alternatif décrivant le glyphe. Les apps qui exposent des libellés d’accessibilité ou qui envoient des glyphes à des destinataires ne prenant pas en charge les glyphes l’utilisent.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 vérifient cette propriété pour piloter une gestion adaptée 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 grâce aux fonctionnalités d’image adaptative de HEIC ; le système choisit la bonne taille selon le contexte de rendu.
Activer les adaptive image glyphs dans UITextView
L’activation tient en une seule propriété1 :
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)
Sans supportsAdaptiveImageGlyph = true, un Genmoji saisi par l’utilisateur apparaît comme un caractère de remplacement (le système ne peut pas afficher le glyphe). Définir la propriété active à la fois le rendu et l’onglet « Genmoji » du clavier système, permettant à l’utilisateur de créer des Genmoji personnalisés au sein de la text view.
Les TextField et TextEditor natifs de SwiftUI n’exposent pas actuellement de modificateur supportsAdaptiveImageGlyph. Les apps SwiftUI qui ont besoin du rendu des adaptive image glyphs encapsulent UITextView dans une 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 nécessite l’architecture de mise en page de TextKit 24. TextKit 1 (le moteur de texte hérité livré avec le modèle original NSTextStorage/NSLayoutManager/NSTextContainer) n’affiche pas correctement les adaptive image glyphs ; le glyphe apparaît comme un placeholder générique ou ne se met pas en page du tout.
Les apps se trouvent dans trois états :
Nouvelles apps sur iOS 18+. TextKit 2 par défaut. UITextView initialisée via Interface Builder ou init(frame:textContainer:) utilise TextKit 2 par défaut sur iOS 16+. Le nouveau code en bénéficie gratuitement.
Apps héritées encore sous TextKit 1. Une migration est requise. La migration vers TextKit 2 n’est pas triviale pour les apps qui sous-classent NSLayoutManager, surchargent les méthodes déléguées liées à la mise en page ou utilisent directement l’ancien NSTextStorage. Le guide de migration TextKit d’Apple couvre le chemin ; pour les apps avec une utilisation simple de UITextView, la migration est essentiellement automatique.
Apps hybrides. Certaines apps intègrent WKWebView pour l’édition HTML aux côtés de UITextView pour l’édition simple. WKWebView gère les adaptive image glyphs via son propre chemin de rendu (pas TextKit), donc 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 emojis personnalisés et que l’autre les supprime.
Intégration avec NSAttributedString
Les adaptive image glyphs circulent à travers 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 d’un texte à l’intérieur d’un autre texte. Le système gère la mise en page (y compris le dimensionnement adaptatif du glyphe en fonction de la police du texte environnant) automatiquement.
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 trouver les glyphes et décider de ce qu’il faut en faire.
Persistance et sérialisation
Le stockage en texte brut (un String, un fichier UTF-8) ne préserve pas les adaptive image glyphs. Le caractère placeholder Unicode qui représente le glyphe dans le texte attribué est sérialisé sous forme de U+FFFC (object replacement) ou de rien du tout, et les véritables données du glyphe sont perdues.
Pour une persistance avec aller-retour fidèle, les apps ont besoin d’un format de texte enrichi5 :
RTFD. Le format texte enrichi + pièces jointes d’Apple. Les adaptive image glyphs y font l’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 pièces jointes) mais sans perte.
HTML avec images intégrées. Adapté au web. Les glyphes sont sérialisés sous forme de balises <img> avec des data URI encodées en base64. Charges utiles plus volumineuses, mais fonctionne avec la plupart des destinataires capables de gérer du texte enrichi.
Markdown avec extensions. Le Markdown standard ne possède pas de syntaxe pour les adaptive image glyphs, mais des 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 du 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 sous 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 de l’audience et de la plateforme.
Échecs courants
Trois schémas issus des journaux d’intégration Genmoji :
Oublier supportsAdaptiveImageGlyph = true. Le bug le plus courant. La text view affiche correctement les emojis Unicode mais Genmoji apparaît comme des caractères placeholder. Correctif : définir la propriété à true dans chaque UITextView/NSTextView qui accepte du texte saisi par l’utilisateur. Pour SwiftUI, utilisez le modificateur .supportsAdaptiveImageGlyph(true).
La persistance en texte brut supprime les glyphes. Enregistrer le contenu de la text view sous forme de text (String brut) jette les Genmoji. L’utilisateur saisit un emoji personnalisé, le voit dans la text view, enregistre le document, le rouvre ; l’emoji a disparu. Correctif : persister sous forme d’attributedText avec un format de texte enrichi qui prend en charge les adaptive image glyphs (RTFD, HTML, format personnalisé avec canal latéral pour pièces jointes).
La transmission réseau supprime silencieusement les glyphes. Une app de messagerie qui sérialise les messages sortants sous forme de texte brut supprime les Genmoji à l’envoi. Le destinataire voit un caractère placeholder ou un espace vide. Correctif : soit envoyer du contenu enrichi (et s’assurer que le destinataire le prend en charge), soit substituer le contentDescription pour les destinataires en texte brut et inclure 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 doivent activer par défaut les adaptive image glyphs. 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 (adaptive image glyphs, réécriture en ligne de Writing Tools, rendu de texte Liquid Glass) supposent toutes TextKit 2. Le coût de migration est réel mais l’alternative consiste à livrer dans un moteur de texte déprécié.
-
Choisissez votre format de persistance en gardant les adaptive image glyphs à l’esprit. RTFD pour le stockage natif iOS ; HTML avec images intégrées pour le stockage compatible web ; format binaire personnalisé avec canal latéral de 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.
Le cluster Apple Ecosystem complet : App Intents typés ; serveurs MCP ; la question du routage ; Foundation Models ; la distinction LLM runtime vs outillage ; trois surfaces ; le pattern source unique de vérité ; Deux serveurs MCP ; hooks pour le développement Apple ; Live Activities ; le contrat runtime watchOS ; internes SwiftUI ; le modèle mental spatial de RealityKit ; discipline de schéma SwiftData ; patterns Liquid Glass ; livraison multi-plateformes ; la matrice des plateformes ; framework Vision ; Symbol Effects ; inférence Core ML ; Writing Tools API ; Swift Testing ; Privacy Manifest ; l’accessibilité comme plateforme ; typographie SF Pro ; patterns spatiaux visionOS ; framework Speech ; migrations SwiftData ; moteur de focus tvOS ; internes @Observable ; protocole Layout SwiftUI ; SF Symbols personnalisés ; HDR AVFoundation ; cycle de vie d’entraînement watchOS ; App Intents 2.0 dans iOS 26 ; API Image Playground ; ce que je refuse d’écrire. Le hub se trouve à 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 activer la fonctionnalité en définissant la propriété à true. Une fois activée, l’onglet Genmoji du clavier système apparaît pour l’utilisateur, et les Genmoji collés s’affichent correctement. Sans activation, un Genmoji saisi ailleurs et collé dans la text view apparaît sous forme de caractères placeholder.
Dois-je avoir Apple Intelligence activé pour tester Genmoji ?
Pour la création complète de Genmoji, oui. Le flux de création Genmoji destiné à l’utilisateur nécessite du matériel compatible Apple Intelligence (iPhone 15 Pro et ultérieur, Macs équipés de puces M) avec iOS 18+ et Apple Intelligence activé. Pour tester en développement le rendu de NSAdaptiveImageGlyph, vous pouvez construire des instances de glyphes de test par programmation avec des données d’image d’exemple et vérifier le rendu de la text view sur n’importe quel appareil ou simulateur iOS 18+.
Que devient un Genmoji lorsque je l’envoie à quelqu’un sous iOS 17 ?
Sans transport de 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 de messagerie) gèrent automatiquement le repli ; les protocoles personnalisés nécessitent une gestion explicite.
Puis-je créer des instances NSAdaptiveImageGlyph par programmation ?
Oui. L’initialiseur public est init(imageContent: Data), prenant des données d’image adaptative HEIC pré-encodées. Les contentDescription, contentIdentifier et contentType sont lus à partir des données encodées plutôt que passés en arguments séparés ; les apps qui créent des adaptive image glyphs personnalisés préparent la charge utile HEIC avec les métadonnées intégrées, puis construisent le glyphe à partir de ces données. La session WWDC 2024 10220 (« Bring expression to your app with Genmoji ») couvre le flux de création complet.
Comment cela interagit-il avec Writing Tools ?
Writing Tools (couvert dans Writing Tools API) préserve les adaptive image glyphs 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 faire l’aller-retour des instances NSAdaptiveImageGlyph correctement à travers leur stockage de texte personnalisé.
Quelle est la différence entre NSAdaptiveImageGlyph et NSTextAttachment ?
NSTextAttachment est l’ancien système de pièces jointes plus large pour le contenu non textuel intégré (images, fichiers, dessins personnalisés) dans le texte attribué. NSAdaptiveImageGlyph est la spécialisation iOS 18 pour les images intégrées de type emoji qui s’adaptent aux caractéristiques de la police environnante. Les deux sont rattachés via les attributs des chaînes attribuées mais utilisent des clés différentes (.attachment vs .adaptiveImageGlyph) et des chemins de rendu différents (TextKit 1+TextKit 2 vs TextKit 2 uniquement). Le nouveau code ciblant le contenu de style Genmoji utilise NSAdaptiveImageGlyph.
Références
-
Documentation développeur Apple :
supportsAdaptiveImageGlyph. La propriété d’activation déclarée sur le protocoleUITextInputauquelUITextViewse conforme ; la même propriété est donc accessible viatextView.supportsAdaptiveImageGlyph. ↩↩ -
Documentation développeur Apple :
NSAdaptiveImageGlyph. Le type de données encapsulant le contenu de l’image, l’identifiant, la description et le type de contenu. ↩↩ -
Documentation développeur Apple :
NSAttributedString.Key.adaptiveImageGlyphetNSAttributedString(adaptiveImageGlyph:attributes:). La surface d’intégration des chaînes attribuées pour les adaptive image glyphs. ↩↩ -
Documentation développeur Apple : guide de migration TextKit 2. Le chemin de migration depuis le moteur de mise en page hérité TextKit 1 vers TextKit 2, requis pour le rendu des adaptive image glyphs. ↩
-
Documentation développeur Apple :
NSAttributedString.DocumentType. Les formats de texte enrichi pris en charge (RTFD, HTML, etc.) pour l’aller-retour des adaptive image glyphs à travers la persistance. ↩