La estructura técnica interna del editor de texto de Apple
- Explica en detalle cómo funciona Paper como editor de texto basado en
TextView.
- Actualmente, Paper está construido sobre el framework TextKit 1, y en TextKit 2 los conceptos, abstracciones y principios se mantienen o cambian por APIs mejores.
Vista de texto
- La clase
TextView es el núcleo del trabajo de edición de texto en el editor de texto de Apple.
- Aunque
NSTextView y UITextView tienen diferencias, sus APIs son similares, por lo que se tratan como una sola clase TextView.
TextView es un componente masivo cuya complejidad aumenta con cada lanzamiento del sistema operativo.
- Apple descompone
TextView en varias capas para ofrecer la experiencia de edición de texto.
NSTextStorage
- Almacena la cadena de texto sin procesar.
- Almacena atributos asignados a rangos de texto (pares cadena-valor).
- Genera eventos ante cambios en el texto y en los atributos.
NSTextContainer
- Define la forma y el tamaño del área que aloja los glifos de texto.
NSLayoutManager
- Calcula el tamaño y el espaciado de los glifos revisando los rangos de atributos aplicados a la cadena de texto de
NSTextStorage.
- Distribuye los glifos y calcula dónde empieza y termina cada línea de texto, así como la altura total del texto.
TextView
- Dibuja la distribución de glifos generada por
NSLayoutManager.
- Sincroniza la altura de la vista con la altura actual del texto ya distribuido.
- Administra la selección de texto, el cursor y los atributos de escritura que se aplican al texto recién insertado.
ScrollView
- Muestra la parte visible de
TextView.
- Administra el desplazamiento, las barras de desplazamiento y el zoom.
Atributos
NSAttributedString es la base de la edición de texto enriquecido en los frameworks de Apple.
- Está compuesto por una cadena de texto simple y atributos adjuntos a rangos de texto (pares cadena-valor).
- Los atributos se usan principalmente con fines de estilo, pero no hay restricciones para asignar pares personalizados de cadena-valor.
Estilo
- Dar estilo significa aplicar atributos especiales definidos por el framework a rangos de texto.
- Paper usa metaatributos para identificar la estructura del texto y luego aplicar el estilo.
- Los atributos se sincronizan con el texto Markdown de
NSTextStorage, que cambia por la entrada del usuario, y con la configuración que afecta al texto, que el usuario ajusta desde elementos de menú, deslizadores y gestos.
Rendimiento
- La separación entre atributos meta, de layout y de decoración ayuda a mantener rápidamente ciertos cambios del editor.
- La velocidad de escritura es el factor de rendimiento más importante en un editor de texto.
- Debido a cómo funciona Markdown, un cambio en el texto puede afectar el estilo de un párrafo completo.
Metaatributos
- Además de la lógica de resaltado, los metaatributos cumplen un papel importante en varias funciones que necesitan conocer la estructura del texto.
Atajos de formato
- Proporcionan la información detallada necesaria para alternar el estilo del texto Markdown seleccionado.
Navegación entre capítulos
- Ayudan a encontrar encabezados en relación con la posición del cursor.
Esquema (Outline)
- Depende de la capacidad de recorrer todos los encabezados.
Reorganización de capítulos
- Proporciona la función para reorganizar capítulos desde el esquema.
Conversión de formatos
- Es necesario conocer la estructura para convertir contenido Markdown a RTF, HTML y DOCX.
Matemáticas del contenedor de texto
- La regla más importante del contenedor de texto es mantener la longitud de línea preferida.
- A veces es necesario aparentar simetría, como cuando las etiquetas de encabezado se colocan fuera del flujo normal del texto.
Anclaje de selección
- La selección de texto siempre tiene un punto de anclaje.
- En Mac se selecciona texto haciendo clic y arrastrando, y en iOS se puede arrastrar uno de los extremos de la selección.
Afinidad de selección
- En la edición de texto existe un concepto interesante llamado afinidad de selección.
- Al mover el cursor con las teclas de flecha, simplemente cambia de línea, pero al moverse al final de la línea con un atajo, permanece en la misma línea y se pega a la derecha.
Uniform Type Identifiers (UTIs)
- Se habla de los UTIs, el sistema base para el intercambio de datos entre apps.
- Es un sistema jerárquico en el que los tipos de datos conform to (heredan de) tipos de datos padre.
Portapapeles (Pasteboard)
- El portapapeles es un diccionario donde los UTIs se asignan a datos serializados.
- Una sola operación de copiar escribe varias representaciones del mismo dato al mismo tiempo.
- Trabajar con UTIs públicos y privados es relativamente simple, pero manejar formatos ampliamente aceptados que no están definidos por Apple es más complejo.
Cierre
- Si revisas el primer artículo, podrás encontrar más información sobre la app y el proceso de desarrollo.
Opinión de GN⁺
- Este artículo explica en detalle el complejo funcionamiento interno de un editor de texto basado en
TextView en plataformas Apple, y ofrece información interesante para desarrolladores de software o usuarios interesados.
- Los algoritmos de optimización de rendimiento y los métodos de gestión de atributos del editor de texto son buenos ejemplos que los desarrolladores pueden tomar como referencia al diseñar sus propias aplicaciones.
- El enfoque técnico usado para mejorar el rendimiento del editor de texto ofrece pautas útiles para que otros desarrolladores consulten al resolver problemas similares.
- Al desarrollar aplicaciones que manejan formatos de texto como Markdown, entender los UTIs es importante para el intercambio de datos y la compatibilidad.
- Este artículo ayuda a comprender mejor la estructura interna de un editor de texto, aunque gestionar esa complejidad en la práctica puede ser un desafío considerable para los desarrolladores.
1 comentarios
Comentarios de Hacker News
Este artículo es realmente bueno. Creo que reemplazará a https://www.objc.io como mi material introductorio básico sobre TextKit.
Estoy un poco confundido acerca de los atributos decorativos que se realizan fuera de la transacción de edición. Dice: "Y no son conscientes de la transacción, porque existen en NSLayoutManager mismo, no en NSTextStorage". ¡Pero los atributos decorativos, como el color, normalmente existen en NSTextStorage! ¿El autor está insinuando que el color aplicado a los caracteres de Markdown se logra mediante el soporte de atributos temporales de NSLayoutManager (normalmente usado para colorear palabras mal escritas)? Si es así, ¿cuál sería el propósito?
Qué gran artículo (y además, personalmente, muy oportuno. Ahora mismo estoy trabajando con NSTextViews). ¿Cómo obtuviste esta información? ¿Código de otra gente? ¿Experiencia dolorosa? ¿developer.apple.com?
En la era de los documentos DOM (por ejemplo, notion, gitbook), a menudo uso cadenas con atributos para hacer cosas casi mágicas con el parseo y la manipulación de texto. Es una estructura muy elegante y no entiendo por qué es tan poco conocida. Por cierto, el artículo es increíble.
En el pasado intenté escribir mi propio editor de texto desde cero, y un recurso como este me habría parecido increíble.
Como fui desarrollador de apps Android durante mucho tiempo, me pareció interesante ver cómo Apple aborda las cosas de una forma algo diferente y más cuidadosa. En Android, la clase Layout (y sus subclases) maneja todo lo relacionado con el layout y el renderizado, mientras que TextView implementa parte de la lógica de edición/selección. La única diferencia entre EditText y TextView es que EditText "activa" la funcionalidad de edición que ya existe en TextView. El problema de este enfoque algo monolítico (y de la API deficiente) es que, si tu app necesita más control sobre cómo renderiza el texto, te quedas sin suerte. Por ejemplo, ¿quieres acceder a glifos individuales después de que ya se hizo el layout? No, lo siento.
La app TextEdit está compuesta casi por completo por un solo TextView. Supongo que WordPad es su equivalente en Windows. Está basado en el control RichEdit. Otro dato curioso es que RTF es básicamente una forma serializada de NSAttributedString. Lo mismo aplica al control RichEdit de Windows. De hecho, parece que la implementación de Windows salió primero: https://en.wikipedia.org/wiki/Rich_Text_Format
Me encanta esta app. ¡Reemplazó a todas mis otras apps de Markdown, incluyendo obsidian y ia Writer!
Por suerte, al menos alguien sigue usando Cocoa en 2024.
¡Ojalá hubiera más documentación como esta sobre componentes de iOS!