L’architecture technique interne de l’éditeur de texte Apple
- Présentation détaillée du fonctionnement de Paper en tant qu’éditeur de texte basé sur
TextView.
- Paper est actuellement construit sur le framework TextKit 1, et dans TextKit 2, les concepts, abstractions et principes sont conservés ou remplacés par de meilleures API.
Vue de texte
- La classe
TextView est au cœur des opérations d’édition de texte dans l’éditeur de texte d’Apple.
NSTextView et UITextView présentent des différences, mais leurs API sont similaires, si bien qu’ils sont traités comme une seule classe TextView.
TextView est un composant massif dont la complexité augmente à chaque version de l’OS.
- Apple découpe
TextView en plusieurs couches pour fournir l’expérience d’édition de texte.
NSTextStorage
- Stocke la chaîne de texte brute.
- Stocke les attributs assignés à des plages de texte (paires chaîne-valeur).
- Déclenche des événements lors des modifications du texte et des attributs.
NSTextContainer
- Définit la forme et la taille de la zone qui héberge les glyphes du texte.
NSLayoutManager
- Calcule la taille et l’espacement des glyphes à partir des plages d’attributs appliquées à la chaîne de texte de
NSTextStorage.
- Met en page les glyphes et calcule où chaque ligne du texte commence et se termine, ainsi que la hauteur totale du texte.
TextView
- Dessine la mise en page des glyphes générée par
NSLayoutManager.
- Synchronise la hauteur de la vue avec la hauteur actuelle du texte mis en page.
- Gère la sélection du texte, le curseur et les attributs de saisie appliqués au texte nouvellement inséré.
ScrollView
- Affiche la partie visible de
TextView.
- Gère le défilement, les barres de défilement et le zoom.
Attributs
NSAttributedString est la base de l’édition de texte enrichi dans les frameworks Apple.
- Il se compose d’une chaîne de texte brute et d’attributs (paires chaîne-valeur) attachés à des plages de texte.
- Les attributs sont principalement utilisés à des fins de style, mais rien n’empêche d’assigner des paires chaîne-valeur personnalisées.
Style
- Le style consiste à appliquer des attributs spéciaux définis par le framework à des plages de texte.
- Paper utilise des méta-attributs pour identifier la structure du texte, puis applique le style.
- Les attributs sont synchronisés avec le texte Markdown de
NSTextStorage, modifié par les entrées de l’utilisateur, ainsi qu’avec les réglages influençant le texte que l’utilisateur ajuste via des éléments de menu, des curseurs et des gestes.
Performances
- La séparation entre attributs de méta, de mise en page et de décoration aide à maintenir rapidement certaines modifications de l’éditeur.
- La vitesse de frappe est l’élément de performance le plus important dans un éditeur de texte.
- En raison du fonctionnement de Markdown, une modification du texte peut affecter le style d’un paragraphe entier.
Méta-attributs
- Au-delà de la logique de surlignage, les méta-attributs jouent un rôle important dans diverses fonctionnalités qui doivent connaître la structure du texte.
Raccourcis de formatage
- Fournissent les informations détaillées nécessaires pour basculer le style du texte Markdown sélectionné.
Navigation entre chapitres
- Aident à trouver le titre relatif à la position du curseur.
Plan (Outline)
- Repose sur la capacité à parcourir tous les titres.
Réorganisation des chapitres
- Fournit la possibilité de réorganiser les chapitres dans le plan.
Conversion de format
- La structure doit être connue pour convertir le contenu Markdown en RTF, HTML ou DOCX.
Mathématiques du conteneur de texte
- La règle la plus importante pour le conteneur de texte est de conserver la longueur de ligne préférée.
- Il faut parfois simuler une symétrie, par exemple lorsque les balises de titre sont placées en dehors du flux normal du texte.
Ancrage de la sélection
- Une sélection de texte possède toujours un point d’ancrage.
- Sur Mac, on sélectionne le texte en cliquant puis en faisant glisser ; sur iOS, on peut faire glisser l’une des extrémités de la sélection.
Affinité de sélection
- Il existe en édition de texte un concept intéressant appelé affinité de sélection.
- Quand on déplace le curseur avec les touches fléchées, il change simplement de ligne ; mais lorsqu’on va en fin de ligne avec un raccourci, il reste sur la même ligne et s’attache à droite.
Uniform Type Identifiers (UTIs)
- Discussion sur les UTI, le système de base des échanges de données entre applications.
- Il s’agit d’un système hiérarchique dans lequel les types de données enfants conform to (héritent de) types de données parents.
Presse-papiers (Pasteboard)
- Le presse-papiers est un dictionnaire qui associe des UTI à des données sérialisées.
- Une seule opération de copie écrit simultanément plusieurs représentations d’une même donnée.
- Gérer les UTI publiques et privées est relativement simple, mais traiter des formats largement acceptés sans être définis par Apple est plus complexe.
Conclusion
- En consultant le premier article, on peut obtenir davantage d’informations sur l’application et le processus de développement.
L’avis de GN⁺
- Cet article détaille le fonctionnement interne complexe d’un éditeur de texte basé sur
TextView sur les plateformes Apple, et offre des informations intéressantes aux développeurs logiciels comme aux utilisateurs curieux.
- Les algorithmes d’optimisation des performances et les méthodes de gestion des attributs d’un éditeur de texte constituent de bons exemples dont les développeurs peuvent s’inspirer pour concevoir leurs propres applications.
- L’approche technique utilisée pour améliorer les performances de l’éditeur de texte fournit des indications utiles à d’autres développeurs confrontés à des problèmes similaires.
- Pour développer des applications qui manipulent des formats textuels comme Markdown, la compréhension des UTI est importante pour l’échange de données et la compatibilité.
- Cet article aide à mieux comprendre la structure interne d’un éditeur de texte, mais gérer concrètement une telle complexité peut représenter un défi considérable pour les développeurs.
1 commentaires
Avis Hacker News
Cet article est vraiment excellent. Il va probablement remplacer https://www.objc.io comme ma ressource d’introduction de base à TextKit.
Je suis un peu perplexe au sujet des attributs décoratifs appliqués en dehors de la transaction d’édition. Il dit : « et ils ne sont pas conscients de la transaction, parce qu’ils existent dans NSLayoutManager lui-même, et non dans NSTextStorage ». Pourtant, les attributs décoratifs comme la couleur se trouvent généralement dans NSTextStorage ! L’auteur sous-entend-il que la couleur appliquée aux caractères Markdown passe par la prise en charge des attributs temporaires de NSLayoutManager (habituellement utilisée pour colorer les mots mal orthographiés) ? Si oui, quel en serait l’intérêt ?
Vraiment un excellent article (et personnellement très opportun : je travaille justement avec des NSTextView en ce moment). Comment as-tu obtenu ces informations ? En lisant le code de quelqu’un d’autre ? Par une expérience douloureuse ? Sur developer.apple.com ?
À l’ère des documents DOM (par ex. notion, gitbook), j’utilise souvent les chaînes de caractères attribuées pour faire des choses presque magiques en analyse et manipulation de texte. C’est une structure très élégante, et je ne comprends pas pourquoi elle est si peu connue. Au passage, l’article est incroyable.
J’ai déjà essayé, par le passé, d’écrire mon propre éditeur de texte from scratch, et avoir une ressource comme celle-ci aurait été formidable.
Comme j’ai été développeur d’apps Android pendant longtemps, j’ai trouvé intéressant de voir qu’Apple aborde les choses d’une manière un peu différente et plus réfléchie. Sur Android, la classe Layout (et ses sous-classes) gère tout ce qui touche à la mise en page et au rendu, et TextView implémente une partie de la logique d’édition/sélection. La seule différence entre EditText et TextView, c’est qu’EditText « active » des capacités d’édition déjà présentes dans TextView. Le problème avec cette approche assez monolithique (et avec une API médiocre), c’est que si une app a besoin de plus de contrôle sur la façon dont elle rend le texte, elle n’a pas de chance. Par exemple, si vous voulez accéder à des glyphes individuels après la mise en page ? Non, désolé.
L’app TextEdit est composée presque entièrement d’une seule TextView. Je suppose que son équivalent sur Windows est WordPad. Celui-ci repose sur le contrôle RichEdit. Autre fait amusant : le RTF est fondamentalement une forme sérialisée de NSAttributedString. Il en va de même pour le contrôle RichEdit de Windows. En fait, il semble que l’implémentation Windows soit arrivée en premier : https://en.wikipedia.org/wiki/Rich_Text_Format
J’adore vraiment cette app. Elle a remplacé toutes mes autres apps Markdown, y compris obsidian et ia Writer !
Heureusement, au moins quelqu’un utilise encore Cocoa en 2024.
J’aimerais qu’il y ait plus de documentation de ce genre sur les composants iOS !