2 puntos por GN⁺ 12 시간 전 | 2 comentarios | Compartir por WhatsApp
  • En macOS, si creas una UI de chat Markdown usando solo SwiftUI, puedes obtener un rendimiento base aceptable, pero es difícil soportar la selección de todo el documento
  • Si lo migras a NSTextView y TextKit 2, pierdes el trabajo de pruebas y rendimiento hecho en SwiftUI, y aparecen picos de CPU con la entrada en streaming
  • Reimplementar con NSCollectionView provoca parpadeo de celdas, y usar solo TextKit 2 ofrece un rendimiento aceptable pero una mala integración con el streaming
  • WebKit encaja bastante bien en renderizado Markdown, rendimiento, tipografía y nivel de control; además, en Electron el trabajo con texto funciona de forma predeterminada
  • En chats largos y texto enriquecido, SwiftUI y los SDK nativos de Apple se vuelven una limitación, mientras que lo basado en web tiene ventaja en el modelo de texto y renderizado

Límites de una UI de chat Markdown nativa en macOS

  • Si construyes un chat simple con soporte Markdown usando solo SwiftUI, puedes lograr un rendimiento base razonable, pero no puedes seleccionar el documento Markdown completo si está compuesto con primitivas de SwiftUI
  • Si lo mueves a NSTextView, ganas soporte de TextKit 2, pero pierdes gran parte del trabajo de pruebas y rendimiento que ya habías hecho en SwiftUI, y además deja de encajar bien con SwiftUI
  • Si insertas respuestas del modelo en NSTextView mediante streaming, se producen picos de CPU
  • Aunque se reimplemente con NSCollectionView, las celdas siguen parpadeando, y eso termina siendo un comportamiento difícil de evitar por diseño
  • Un prototipo puro con TextKit 2 tiene un rendimiento aceptable, pero el streaming sigue funcionando mal y no encaja bien con componentes modernos
  • Incluso si eliminas por completo SwiftUI y usas solo AppKit, tienes que manejar manualmente fragmentos de texto que se van expandiendo, y la selección de texto solo se vuelve posible cuando muchas partes ya están rotas
  • Para llegar a un nivel similar al comportamiento básico de macOS, hay que volver a ajustar funciones que el usuario da por sentadas, como menús contextuales, consulta en diccionario, selección, accesibilidad e interacción con texto

Dónde encajan mejor WebKit y Electron

  • Si renderizas Markdown con WebKit, hay algunos puntos a cuidar, pero en general funciona bien, ofrece buen rendimiento y tipografía, y también un nivel de control suficiente
  • Si haces un proyecto simple con Electron, el trabajo con texto, el renderizado Markdown y una buena tipografía funcionan desde el inicio, y además se obtiene un rendimiento que fue más difícil de conseguir en una implementación pura con TextKit 2
  • Electron también ofrece integración con macOS, permite renderizar vistosos Git diff con unas cuantas líneas de código, y existen casos como diffs.com
  • Incluso revisando SwiftUI, AppKit, TextKit y WebKit, sigue siendo difícil cumplir bien un requisito tan simple como “un chat con soporte Markdown donde se pueda seleccionar el mensaje completo”
  • Queda más claro por qué las nuevas apps donde importan el chat, el texto enriquecido de formato largo y la tipografía flexible terminan yéndose a la web
  • SwiftUI es adecuado para pantallas simples sin mucho desplazamiento, y Swift sigue siendo útil en partes donde el rendimiento es importante
  • Electron o React Native pueden obtener bastante rendimiento gracias a la interoperabilidad nativa, mientras mantienen un mejor modelo de texto y renderizado
  • En el renderizado de texto enriquecido para chats de formato largo, SwiftUI y los SDK nativos de Apple dejan de ser una ventaja y pasan a ser una limitación
  • Discusión relacionada: Hacker News, Lobsters

2 comentarios

 
Comentarios en Hacker News
  • Hace poco lancé un editor de texto para iOS usando TextKit 2, y el rendimiento sale muy bien incluso con archivos de 5,000 líneas
    Lo probé con Moby Dick de Project Gutenberg, lo hice entre agosto de 2025 y abril de 2026, y el desarrollo sigue en marcha
    Con cada pulsación de tecla se vuelve a aplicar el estilo en menos de 8 ms, y hasta una ráfaga rápida de 20 pulsaciones se procesa en 150 ms incluyendo el reestilizado completo tras cada entrada, sin debouncing ni renderizado diferido
    Las búsquedas por etiquetas y booleanas terminan en menos de 20 ms, y renderizar solo el rango visible es 25 veces más rápido que aplicar estilo a todo el documento, además de soportar refresco de pantalla a 120 Hz
    El tamaño del archivo de la app era 722 KB en la versión 1.0, y la 1.1, con más funciones, parece quedar en unos 950 KB
    Si este nivel es posible en iOS, en macOS debería ser unas 10 veces más fácil
    https://www.gingerbeardman.com/apps/papertrail/

    • Si la función principal de un producto de pago es el editor, se entiende. Pero si el renderizado de Markdown ni siquiera es la función principal de la app y en 2026 es más bien una comodidad que el usuario espera, se siente raro que para eso haya que hacer una implementación personalizada de bajo nivel con la mentalidad de dedicarle 8 meses y seguir desarrollándola
      No es que sea “imposible”; más bien entiendo por qué la gente elige tecnologías web en vez de lo nativo para este tipo de cosas. Uno quiere construir el producto, no pelearse con las limitaciones del sistema
    • Habiendo hecho en 2012 una novela interactiva con NSString y atributos, un roguelike con la antigua API de glifos de bajo nivel ya descartada, dos apps de chat con soporte Markdown en SwiftUI y un idle game mezclando trucos de iOS, termino resumiendo esta reacción como un problema de experiencia
    • 5,000 líneas es realmente muy poco, así que esta explicación me confunde. El Moby Dick con el que dicen haber probado parece tener más de 22,000 líneas, y ni siquiera el Bloc de notas predeterminado de Windows se traba con un archivo así
      Si es un visor de texto, debería manejar al menos archivos dos órdenes de magnitud más grandes. Los archivos JSON de cientos de miles de líneas son comunes, y los CSV y logs suelen ser todavía más largos
    • Probablemente la implementación de SwiftUI en Mac no sea muy buena. Para una app así quizá SwiftUI sobre Catalyst sea mejor, aunque seguramente traería otros problemas
    • Dudo mucho de eso de que si funciona en iOS en macOS sería 10 veces más fácil. Más bien pensaría justo lo contrario, y me gustaría escuchar a alguien que realmente sepa del tema
  • Antes normalmente se usaban APIs nativas en lugar de webviews por rendimiento, pero ahora ya no parece necesariamente cierto
    Los motores de renderizado de los navegadores están bastante maduros, tienen mucha aceleración por GPU y llevan más de diez años siendo sometidos a pruebas de estrés con aplicaciones web infladas
    En cambio, SwiftUI no se siente particularmente rápido. Incluso la Configuración del Sistema que Apple rehizo como lo más moderno, simplificando la UI en filas de casillas, a veces cambia de sección con más tirones que cargar una página web desde us-east-1

    • El problema aquí no son las apps nativas en general, sino SwiftUI
      He creado apps nativas con Qt C++ y QML, y he demostrado que son mucho más rápidas y usan mucha menos RAM que apps web similares
      Así que, en general, las apps web sí son más lentas y consumen más recursos que una app nativa bien diseñada
      [1] https://notes.alinpanaitiu.com/SwiftUI%20is%20convenient,%20...
      [2] https://x.com/daniel_nguyenx/status/1734495508746702936
      [3] https://rubymamistvalove.com/block-editor#8-performance
    • Aun así, sigue habiendo una gran diferencia entre una app nativa y la app de navegador más ligera, y en dispositivos de bajo consumo se nota todavía más
      Yo era desarrollador web, pero en los últimos 6 a 12 meses empecé a hacer apps nativas multiplataforma, y hasta en tareas simples la brecha de rendimiento es bastante clara
    • Los navegadores son terribles en hardware viejo. Los Chromebook antiguos son comunes y están bien de especificaciones para tareas ligeras o propósitos específicos, pero el navegador va realmente lento
    • En una app web simple puede no notarse, pero en aplicaciones complejas sí hay lentitud visible. Ni siquiera hace falta llegar a monstruos como Jira; hasta una app tan bien optimizada como VS Code tiene un techo de rendimiento más bajo que una app nativa
    • Un WebView al final también es “nativo”
      Me parece extraño descartar miles de años-persona de optimización y millones de años-persona de validación en condiciones reales para volver a inventar un motor de renderizado de texto peor
  • En macOS, WebKit es un framework nativo del sistema operativo. Usar WebKit para renderizar Markdown me parece totalmente razonable
    Obviamente, renderizarlo todo con WebKit tendría tan poco sentido como renderizarlo todo con PDFKit. Pero para una vista de Markdown, WebKit es una elección lógica, y eso no significa que haya que dar el salto completo a una app web con Chromium

    • Si un motor HTML renderiza mejor texto enriquecido, que quizá sea de lo más difícil de renderizar en una UI, que las librerías nativas de UI, entonces ¿por qué no usarlo también para renderizar cosas más fáciles como botones o campos de texto?
      Además, durante mucho tiempo OS X renderizó la UI con DisplayPDF/Quartz
    • Haría falta explicar por qué renderizar Markdown con WebKit sería algo apropiado
    • Parece que el autor original entiende “nativo” como usar solo los elementos primitivos de Swift/ObjC
      ¿WebKit sería hacer trampa porque también existe en otras plataformas? Si ese es el criterio, entonces también se podría usar Java
    • No veo por qué deberíamos esperar usar WebKit para renderizar texto enriquecido
      Si renderizar texto con un renderizador HTML/CSS/JS es “totalmente apropiado”, ¿qué área no lo sería? ¿Por qué no renderizar todo con eso?
      No entiendo la lógica que va de “para renderizar texto está bien” a “pero para renderizar todo sería absurdo”
    • De hecho, la solución que estamos implementando ahora mismo es renderizar el Markdown final y el streaming con WebKit
      Coincido en que WebKit es un framework nativo del sistema en macOS y que, en ese sentido, es “nativo”
      Pero eso también refuerza la idea más amplia de que, para manejar bien texto enriquecido, Markdown, selección, tipografía y contenido largo con formato, las tecnologías web se vuelven rápidamente la única opción realmente práctica
      No es que usar WebKit para una vista Markdown esté mal; al contrario, probablemente sea la decisión más razonable. El problema es que aquí la solución “nativa” en la práctica termina siendo una solución de renderizado web
      Cada WKWebView trae consigo un motor WebKit con su propio costo de rendimiento y memoria, así que no se puede esparcir por toda la interfaz y tratar como si fuera un componente nativo gratuito de macOS
      Frustra que para este tipo de UI SwiftUI / AppKit / TextKit no ofrezcan una ruta más limpia, moderna y componible que “simplemente usa WebKit”
  • Parece absurdo que algo como “permitir seleccionar el mensaje completo en un chat con Markdown” no funcione
    En SwiftUI se puede aprovechar un renderizador de Markdown maduro. Basta ver https://github.com/gonzalezreal/swift-markdown-ui y su reemplazo de próxima generación https://github.com/gonzalezreal/textual
    Yo los he usado y no tuve problemas. Incluso yo, que tontamente no soy fan de Swift ni de SwiftUI y prefiero Objective-C, lo saqué adelante sin ayuda de LLMs

    • Hoy más temprano probé Textual y los resultados no fueron muy buenos
      El scroll de Markdown estático ya completado no pasó una nueva prueba de foco: p95 de 18.86 ms, por encima del presupuesto de 16.7 ms, y máximo de 232.49 ms
      La ruta de actualizaciones largas en tiempo real de Markdown/código también falló: p95 de 59.33 ms frente a 16.7 ms, con máximo de 75.94 ms. Es un caso de estrés aparte pero relacionado al manejar superficies grandes de texto enriquecido durante actualizaciones
      La expansión de historial largo técnicamente pasa, pero difícilmente se puede llamar fluida: 120 turnos p95 de 21.35 ms, 500 turnos 23.11 ms, 1000 turnos 36.77 ms
      No está mal, pero es un poco más lento que mi solución, y la diferencia de rendimiento parece estar relacionada sobre todo con SwiftUI más que con la implementación específica de Textual
    • ¿Puede manejar texto en streaming sin parpadeos?
    • Si solo vas a renderizar un documento Markdown una vez, o si el documento es simple y corto, seguramente sí
      Yo usé swift-markdown-ui en una app antes, pero el rendimiento ni se acercaba a wkwebview. Si haces streaming de documentos grandes con elementos complicados como tablas grandes, bloques de código y citas anidadas, hasta puedes ver la pelota de playa; con wkwebview eso no me pasaba
    • Parece que la primera librería la usa la app de Claude para iOS, y además de permitir selección de texto y streaming, el rendimiento se ve bastante bien
    • Como usuario, sí se nota que muchas apps antiguas no basadas en HTML no siguen las “reglas”. Hay texto que debería poder seleccionarse pero no se puede, o no se copia con control/option C, cosas así
      Luego uno se da cuenta de que los navegadores y las tecnologías en las que se apoyan introdujeron un nuevo paradigma de UI, y que los frameworks nativos de UI no lograron mantenerse al día
      Lo digo incluso prefiriendo las apps nativas sobre las basadas en web
  • O muestran el código o mejor se salen. Incluso ahora hay muchísimas apps nativas para Mac/iOS que manejan bien el renderizado Markdown y el texto en streaming
    Solo me da curiosidad saber qué excusa hay exactamente

    • Dicen “quiero poder seleccionar un documento Markdown completo hecho con elementos primitivos de SwiftUI”, pero ¿quién quiere eso? Tomar esa decisión de producto equivale en la práctica a querer construir un editor de documentos, un terreno difícil desde hace décadas y que parece ir mucho más allá del alcance de una UI de chat con LLM
      La mayoría terminó asentándose en soportar selección solo dentro de cada bloque continuo y poner un botón de copiar para el mensaje completo
    • Si se puede hacer sin webview, bastaría con compartir el código
  • Un dato curioso es que Apple ya hizo esto antes
    El antiguo macOS / AppKit usaba WebKit para renderizar texto enriquecido dentro de NSTextField nativo. El texto es un problema difícil
    Además, el WebView nativo es muy rápido y ligero, así que no es raro usarlo como motor de maquetación de texto. Incluso usar un WebView separado por cada fila de una tabla puede dar un rendimiento excelente
    iMessage para Mac también usaba WebView, y Adium igual. Si estás renderizando texto enriquecido/de marcado, HTML es una herramienta totalmente adecuada

    • Aquí se están confundiendo iOS y Mac OS
      Mac nunca usó WebKit para renderizar NSTextField. Cuando iOS se creó por primera vez, sí usaba WebKit como renderizador de texto de forma bastante general, incluso para controles de UIKit, y a eso le llamaban la “sweet solution”
      Pero resultó ser demasiado pesado y engorroso, así que se pasó al enfoque de renderizado de texto al estilo Core Text/AppKit
    • El hilo original se siente un poco raro
      Descubren que el renderizado complejo de texto nativo es difícil, empiezan a renderizar texto con un enfoque de bajo nivel y luego se quejan de tener que volver a implementar interacciones nativas
      Prueban WebKit y funciona muy bien, pero aun así lo descartan para volver a una situación donde tienen que reimplementar interacciones nativas
      Personalmente, yo me habría detenido justo en el punto en que WebKit funciona bien
  • Recuerdo que en 2015, cuando era ingeniero junior, me tocó una tarea de renderizar enlaces clicables dentro de un párrafo en una app de iOS
    Swift acababa de salir, así que era todo stack ObjC/UIKit, y fue una auténtica pesadilla. Apenas logré hacerlo funcionar
    Como desde más o menos 2016 casi no he tocado iOS, asumí que el nuevo SwiftUI obviamente ya traería esto de fábrica, así que saber que no es así suena bastante loco

    • Literalmente existe Link
      https://developer.apple.com/documentation/swiftui/link
      A estas alturas no sé cómo podría hacerse más fácil
    • Qt ya permitía hacer esto con bastante facilidad hace 10 años
    • ¿No estaba NSLinkAttributeName?
    • Yo pensaba que el texto con atributos resolvía bien esto desde hace mucho, ¿no?
    • El simple hecho de pedir enlaces clicables dentro de un párrafo ya era una mala idea
  • Que “lo nativo siga siendo tan inmaduro en cuanto sales de pantallas simples” es algo esperable
    Si la gente no invierte suficiente esfuerzo, no puedes esperar que eso madure
    Como cada vez más esfuerzo se va hacia tecnologías web, la gente queda atada a eso. Ven lo nativo, dicen que “todavía no está lo bastante desarrollado” y luego vuelven a desarrollar más para la web: se repite el ciclo
    En el navegador ya “simplemente funciona”, así que casi nadie quiere esforzarse en mejorar lo nativo

    • Aun así, ¿los toolkits de UI nativa no son productos comerciales? No debería recaer en la gente convencerse sola; del otro lado son ellos quienes deberían venderle la idea a la gente
      Una de las razones por las que la web es mucho más madura es que los grandes fabricantes comerciales de sistemas operativos no quisieron adaptarse a los tiempos. Los toolkits de UI de Windows son un verdadero desastre
    • De acuerdo. Al final se está quejando de que todavía no se ha puesto mucho esfuerzo en manejar Markdown rápido en Swift, pero al mismo tiempo no parece tener intención de contribuir a eso
  • En mi app de chat con IA tuve casi exactamente la misma experiencia. Nada funciona bien
    El renderizado de Markdown es lento y da tirones, el streaming también es lento y da tirones, y todo termina congelando la UI
    Probé al menos 5 componentes de edición de texto populares en GitHub para UIKit y SwiftUI, y todos estaban rotos de una forma u otra, o tenían bugs y eran lentos. Es absurdo

  • Es un problema difícil. Escribí bastante sobre cómo lo resolví al construir desde cero un editor por bloques con Qt C++ y QML
    Tuve problemas parecidos con la selección entre bloques discontinuos, mostrar el Markdown fuente bajo el cursor y tamaños distintos de delegate
    Con base en lo que aprendí entonces, ahora estoy construyendo un cliente nativo para LLM con un parser de Markdown en streaming
    [1] https://rubymamistvalove.com/block-editor
    [2] https://www.get-vox.com

 
Opiniones de Lobste.rs
  • Estoy de acuerdo en que para layouts de texto complejos un webview tiene sentido, pero no estoy tan seguro de que haya que llegar hasta Electron solo por conveniencia
    Electron es, en esencia, un wrapper alrededor de un WebView, pero como arrastra todo el motor de Chromium, el precio de esa conveniencia es que el tamaño de la app crece demasiado
    En 2001~2002 implementé el icónico layout de texto con globos de chat de iChat usando NSTextView y todo tipo de trucos, y aun con la ayuda de Hideki Itamura, que era diseñador de texto de AppKit, fue bastante sufrido. Hoy en día con HTML+CSS se volvió bastante simple
    • Cuando hay que soportar varios sistemas, al final la simplicidad pesa mucho
      Participé en una app que usaba Tauri, y al cambiarla a Electron para usar Chromium funcionó muchísimo mejor. También importa que apuntaba a un rango muy amplio, especialmente desde win7 hasta win11
      En la familia Tauri parece atractivo usar el webview del sistema, pero en Windows eso significa Chrome o Edge, en macOS Safari, y en otros entornos básicamente depender de la suerte. Al final ganaron la previsibilidad y la madurez, y por alguna razón desconocida el rendimiento también fue mejor
    • Creo que esto es una decisión personal. Si estás dispuesto a pagar el costo en tamaño de la app o uso de RAM a cambio de conveniencia, parece que también lo están los millones de usuarios de apps como Visual Studio Code
      Al final quiero mejor software más que satisfacer la gráfica de htop
      El punto central del post no es “todos deberían elegir Electron”, sino que ahora entiendo por qué incluso empresas con recursos y dinero siguen eligiendo Electron o tecnologías web. Al menos para mí, ofrece una buena experiencia de usuario haciendo concesiones razonables donde corresponde
      Hay mucha gente que defiende TextKit 2 de Apple u otros frameworks nativos de texto, pero casi no existen editores de texto populares y de alto rendimiento hechos solo con el SDK de Apple. Xcode lo hace bastante bien y probablemente sea el único caso cercano a uso real. Zed, Sublime Text, Visual Studio Code y los IDE de JetBrains usan todos soluciones propias de renderizado de texto por una razón
  • Uno de los problemas es que quienes hacen software desarrollan en computadoras y teléfonos que están en el 0.1% superior a nivel mundial
    Entonces, incluso si construyen algo de la peor manera posible, en su propio entorno puede parecer que está bien
    Mientras tanto, el resto de la gente, que usa dispositivos con especificaciones mucho más bajas, termina cargando con software inflado y lento
  • Me pregunto cómo estarán hoy en día las cosas del lado de GTK/Qt. Hace mucho que no hago GUI
    • Según entiendo, esto también se podría implementar en Qt sin usar un webview
      Aunque parece que el autor no exploró esa alternativa hasta ese punto
  • Me pregunto cómo sería comparar Electron con Flutter
    Visto desde fuera, Flutter parece una respuesta a “¿qué pasa si dejamos solo Skia, el renderizador de Chromium, y lo usamos para apps GUI?”. Debería ser una herramienta multiplataforma con funciones parecidas a Electron, pero más ligera
  • El autor de https://github.com/stevengharris/MarkupEditor sugiere que este post presenta una de las mejores soluciones disponibles actualmente: https://blog.krzyzanowskim.com/2025/08/14/textkit-2-the-promised-land/
    • Pero MarkupEditor no usa TextKit2 sino WebView. Incluso en el README dice que MarkupEditor interactúa con un documento HTML que usa un solo DIV contentEditable, y que utiliza una subclase de WKWebView
      Lo irónico es que el motor nativo de texto de Apple usa un modelo de datos mucho mejor que el árbol DOM de HTML: una cadena y atributos de estilo codificados por longitud de ejecución
      Editar texto en el DOM es casi una pesadilla, porque muchas veces la selección atraviesa múltiples elementos en varias capas, así que hay que dividir y fusionar todo de formas muy complejas. Cuando probé por primera vez una build de Safari con soporte para contenteditable, reporté una enorme cantidad de bugs, y aún hoy muchos editores web de texto enriquecido se rompen al cortar o pegar elementos de lista
      Al final, parece que ocurrió algo parecido al CISC vs RISC de los 90~00. Una arquitectura “inferior” terminó produciendo una implementación mejor porque recibió muchos más recursos