Nativ bis zum Schluss – bis man Text braucht
(justsitandgrin.im)- Wenn man unter macOS eine Markdown-Chat-UI nur mit SwiftUI baut, ist die Grundleistung bis zu einem gewissen Grad brauchbar, aber die Auswahl des gesamten Dokuments lässt sich nur schwer unterstützen
- Beim Wechsel zu
NSTextViewund TextKit 2 verliert man die Test- und Performance-Arbeit aus SwiftUI, und bei Streaming-Eingaben entstehen CPU-Spikes - Eine Neuimplementierung mit
NSCollectionViewführt zu flackernden Zellen, und auch reines TextKit 2 hat zwar ordentliche Performance, ist aber für die Integration von Streaming ungeeignet - WebKit passt bei Markdown-Rendering, Performance, Typografie und Grad der Kontrolle insgesamt deutlich besser, und auch in Electron funktionieren Textbearbeitungsvorgänge standardmäßig
- Bei langen Chats und Rich Text werden SwiftUI und die nativen Apple-SDKs zur Einschränkung, während webbasierte Ansätze beim Text- und Rendering-Modell im Vorteil sind
Die Grenzen nativer macOS-Markdown-Chat-UIs
- Wenn man einen einfachen Chat mit Markdown-Unterstützung nur mit SwiftUI baut, ist die Grundperformance bis zu einem gewissen Grad möglich, aber ein vollständiges Auswählen des gesamten Markdown-Dokuments, das aus SwiftUI-Primitiven besteht, ist nicht möglich
- Wechselt man zu
NSTextView, bekommt man Unterstützung für TextKit 2, verliert aber den Großteil der in SwiftUI aufgebauten Tests und Performance-Arbeit, und es passt auch nicht mehr gut zu SwiftUI - Wenn Modellantworten per Streaming in
NSTextVieweingefügt werden, entstehen CPU-Spikes - Selbst bei einer erneuten Implementierung mit
NSCollectionViewflackern die Zellen ständig weiter, was aufgrund des Designs schwer zu vermeiden ist - Ein reiner TextKit-2-Prototyp hat zwar ordentliche Performance, aber Streaming bleibt weiterhin schlecht und es passt nicht gut zu modernen Komponenten
- Selbst wenn man SwiftUI vollständig entfernt und nur AppKit verwendet, muss man wachsende Textfragmente manuell behandeln, und erst nachdem vieles kaputtgeht, wird Textauswahl überhaupt möglich
- Um ein Niveau zu erreichen, das dem grundlegenden Verhalten von macOS ähnelt, muss man Funktionen neu angleichen, die Nutzer selbstverständlich erwarten, etwa Kontextmenüs, Wörterbuch-Nachschlagen, Auswahl, Barrierefreiheit und Textinteraktion
Wo WebKit und Electron besser passen
- Wenn man Markdown mit WebKit rendert, gibt es zwar einige Punkte zu beachten, insgesamt funktioniert es aber gut, bietet gute Performance und Typografie und auch das Maß an Kontrolle ist ausreichend
- Erstellt man ein einfaches Electron-Projekt, funktionieren Textbearbeitung, Markdown-Rendering und gute Typografie standardmäßig, und auch eine Performance, die schwerer zu erreichen war als in einer reinen TextKit-2-Implementierung, ist vorhanden
- Auch in Electron gibt es macOS-Integration, mit ein paar Zeilen Code lassen sich auffällige Git-Diffs rendern, und es gibt Beispiele wie diffs.com
- Selbst wenn man SwiftUI, AppKit, TextKit und WebKit prüft, ist es schwer, die einfache Anforderung eines „Chats mit Markdown-Unterstützung und vollständiger Nachrichtenauswahl“ wirklich zufriedenstellend zu erfüllen
- Es wird klarer, warum neue Apps, bei denen Chat, lange Rich-Text-Formate und flexible Typografie wichtig sind, webbasierte Ansätze wählen
- SwiftUI eignet sich für einfache Oberflächen ohne viel Scrollen, und Swift bleibt in performancekritischen Bereichen weiterhin nützlich
- Electron oder React Native können durch native Interoperabilität erhebliche Performance erreichen und dabei ein besseres Text- und Rendering-Modell beibehalten
- Beim Rich-Text-Rendering für lange Chats werden SwiftUI und die nativen Apple-SDKs nicht zum Vorteil, sondern zur Einschränkung
- Verwandte Diskussionen: Hacker News, Lobsters
2 Kommentare
Hacker-News-Kommentare
Ich habe kürzlich einen Texteditor für iOS veröffentlicht, der TextKit 2 verwendet, und die Performance ist selbst bei Dateien mit 5.000 Zeilen hoch
Getestet wurde mit Moby Dick von Project Gutenberg; gebaut wurde er zwischen August 2025 und April 2026, und die Entwicklung läuft weiter
Nach jedem Tastendruck wird in unter 8 ms neu gestylt, und selbst 20 schnelle Eingaben ohne Debouncing oder verzögertes Rendering werden inklusive vollständigem Restyling nach jeder Eingabe in 150 ms verarbeitet
Tags und boolesche Suche sind in unter 20 ms fertig, und wenn nur der sichtbare Bereich gerendert wird, ist das 25-mal schneller als das Styling des gesamten Dokuments; 120-Hz-Bildschirmaktualisierung wird ebenfalls unterstützt
Die App-Größe lag in 1.0 bei 722 KB, und auch 1.1 mit mehr Funktionen scheint etwa 950 KB groß zu sein
Wenn so etwas auf iOS möglich ist, sollte es auf macOS ungefähr zehnmal einfacher sein
https://www.gingerbeardman.com/apps/papertrail/
Es geht nicht darum, dass es „unmöglich“ wäre, sondern darum, dass ich verstehe, warum Leute für so etwas statt Web-Technologien lieber nicht auf nativ setzen. Man will ein Produkt bauen und nicht mit Systemgrenzen kämpfen
Ein Text-Viewer sollte mindestens Dateien verarbeiten können, die zwei Größenordnungen darüber liegen. JSON-Dateien mit mehreren hunderttausend Zeilen sind üblich, und CSV- sowie Log-Dateien sind noch länger
Normalerweise war Performance der Grund, native APIs statt einer WebView zu verwenden, aber inzwischen scheint das nicht mehr zwingend zu gelten
Browser-Rendering-Engines sind ziemlich ausgereift, stark GPU-beschleunigt und wurden über mehr als ein Jahrzehnt mit aufgeblähten Web-Apps unter Realbedingungen stresstestet
SwiftUI fühlt sich dagegen nicht besonders schnell an. Apple hat sogar die neu geschriebene Systemsteuerung UI-seitig auf Checkbox-Zeilen vereinfacht, und trotzdem ruckeln Bereichswechsel manchmal stärker, als eine Webseite aus us-east-1 zu laden
Ich habe native Apps mit Qt C++ und QML gebaut und gezeigt, dass sie deutlich schneller sind und viel weniger RAM verbrauchen als vergleichbare Web-Apps
Daher sind Web-Apps im Allgemeinen langsamer und ressourcenhungriger als gut entworfene native Apps
[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
Ich war ursprünglich Webentwickler, habe aber in den letzten 6–12 Monaten angefangen, native plattformübergreifende Apps zu bauen, und selbst bei einfachen Aufgaben ist der Performance-Abstand ziemlich groß
Es wirkt seltsam, Tausende Personenjahre an Optimierung und Millionen Personenjahre an Validierung in realen Umgebungen wegzuwerfen, nur um eine schlechtere Text-Rendering-Engine neu zu bauen
Unter macOS ist WebKit ein natives OS-Framework. WebKit für Markdown-Rendering zu verwenden, wirkt völlig angemessen
Natürlich ergibt es genauso wenig Sinn, alles mit WebKit zu rendern, wie alles mit PDFKit zu rendern. Aber für eine Markdown-Ansicht ist WebKit eine logische Wahl, und deshalb muss man noch lange nicht gleich zu einer Chromium-Web-App wechseln
Außerdem hat OS X UI über lange Zeit mit DisplayPDF/Quartz gerendert
Ist WebKit Schummeln, weil es das auch auf anderen Plattformen gibt? Dann könnte man genauso gut Java nehmen
Wenn es „völlig angemessen“ ist, Text mit einem HTML/CSS/JS-Renderer darzustellen, welcher Bereich ist dann nicht angemessen? Warum nicht alles damit rendern?
Ich verstehe die Logik nicht, die von „Text-Rendering ist angemessen“ zu „aber alles zu rendern wäre absurd“ führt
Ich stimme zu, dass WebKit unter macOS ein natives OS-Framework ist und in diesem Sinn also „nativ“
Aber das stützt auch den größeren Punkt, dass Web-Technologien beim korrekten Umgang mit Rich Text, Markdown, Auswahl, Typografie und langem formatiertem Inhalt schnell zur einzigen praktikablen Option werden
Es geht nicht darum, dass WebKit für eine Markdown-Ansicht falsch wäre; im Gegenteil, es ist wahrscheinlich die vernünftigste Wahl. Das Problem ist, dass die „native“ Lösung hier faktisch eine Web-Rendering-Lösung ist
Jede
WKWebViewbringt eine eigene WebKit-Engine mit eigenem Performance- und Memory-Overhead mit, deshalb kann man sie nicht einfach überall verstreuen und wie kostenlose native macOS-Komponenten behandelnFrustrierend ist, dass SwiftUI / AppKit / TextKit für diese Art UI keinen sauberen, modernen und komponierbaren Weg bieten, der besser ist als „nimm einfach WebKit“
Es wirkt absurd, dass so etwas wie „in einem Chat mit Markdown den gesamten Nachrichtentext auswählbar machen“ nicht möglich sein soll
In SwiftUI kann man einen ausgereiften Markdown-Renderer nutzen. Siehe https://github.com/gonzalezreal/swift-markdown-ui und dessen Nachfolger https://github.com/gonzalezreal/textual
Ich habe es selbst verwendet und hatte keine Probleme. Sogar ich, der Swift und SwiftUI nicht mag und Objective-C bevorzugt, habe das ohne Hilfe eines LLM hinbekommen
Das Scrollen durch statisches fertiges Markdown bestand den neuen Fokus-Probe-Test nicht; p95 lag bei 18,86 ms statt im Budget von 16,7 ms, das Maximum bei 232,49 ms
Auch der Pfad für lange Live-Updates von Markdown/Code fiel durch: p95 59,33 ms gegenüber 16,7 ms, Maximum 75,94 ms. Das ist ein separater, aber verwandter Stressfall mit großen Rich-Text-Flächen während Updates
Langes Erweitern des Verlaufs besteht technisch gesehen, fühlt sich aber kaum nach flüssigen Frames an: 120 Turns p95 21,35 ms, 500 Turns 23,11 ms, 1000 Turns 36,77 ms
Nicht schlecht, aber etwas langsamer als meine Lösung, und die Performance-Lücke scheint vor allem eher mit SwiftUI als mit der Textual-Implementierung zusammenzuhängen
Ich habe früher in meiner App swift-markdown-ui genutzt, aber die Performance kam an wkwebview überhaupt nicht heran. Wenn man große Dokumente mit schwierigen Elementen wie großen Tabellen, Codeblöcken oder verschachtelten Zitaten streamt, bekommt man sogar den Beachball zu sehen; mit wkwebview ist mir das nie passiert
Dann merkt man, dass Browser und die darauf basierenden Technologien ein neues Paradigma für UI eingeführt haben, mit dem native UI-Frameworks nicht Schritt gehalten haben
So fühlt es sich selbst für jemanden an, der native Apps Web-Apps vorzieht
Entweder Code zeigen oder raus damit. Es gibt schon jetzt sehr viele native Mac-/iOS-Apps, die Markdown-Rendering und Streaming-Text ordentlich hinbekommen
Ich frage mich nur, was hier eigentlich die Ausrede sein soll
Die meisten sind am Ende dabei gelandet, Auswahl nur innerhalb einzelner zusammenhängender Blöcke zu unterstützen und für die gesamte Nachricht einen Kopier-Button anzubieten
Der interessante Punkt ist, dass Apple das früher selbst so gemacht hat
Früheres macOS / AppKit nutzte WebKit, um Rich Text in nativen NSTextField-Elementen zu rendern. Text ist ein schwieriges Problem
Dazu kommt, dass native WebViews sehr schnell und leichtgewichtig sind, daher ist es nicht seltsam, sie als Text-Layout-Engine einzusetzen. Selbst eine separate WebView für jede Tabellenzeile kann hervorragende Performance liefern
iMessage für den Mac nutzte ebenfalls WebView, und Adium auch. Wenn man Rich-/Markup-Text rendert, ist HTML absolut das richtige Werkzeug
Auf dem Mac wurde WebKit nie für das Rendering von NSTextField verwendet. Als iOS ursprünglich entstand, nutzte es WebKit breit als Text-Renderer, auch in UIKit-Controls, und nannte das die „sweet solution“
Aber das erwies sich als zu schwergewichtig und umständlich, weshalb man zu einem Core-Text-/AppKit-artigen Text-Rendering-Ansatz überging
Man entdeckt, dass komplexes natives Text-Rendering schwierig ist, rendert den Text dann auf Low-Level-Art und beklagt sich anschließend, dass man native Interaktionen neu implementieren muss
Dann probiert man WebKit aus, und es funktioniert sehr gut, nur um es wieder wegzuwerfen und zurück in eine Situation zu gehen, in der man native Interaktionen erneut selbst implementieren muss
Persönlich wäre ich bei dem Punkt stehen geblieben, an dem WebKit gut funktioniert
Ich erinnere mich noch daran, wie ich 2015 als Junior Engineer die Aufgabe bekam, in einem iOS-App-Absatz klickbare Links zu rendern
Swift war gerade erst erschienen, daher war es noch ein kompletter ObjC/UIKit-Stack, und es war wirklich ein Albtraum. Ich habe es mit Mühe irgendwie zum Laufen gebracht
Seit etwa 2016 habe ich mit iOS kaum noch etwas gemacht, deshalb war ich sicher, dass das im neuen SwiftUI selbstverständlich eingebaut sein müsste. Dass das nicht so ist, ist ziemlich verrückt
https://developer.apple.com/documentation/swiftui/link
Ich weiß ehrlich nicht, wie viel einfacher man es noch machen könnte
NSLinkAttributeName?Dass „nativ“ jenseits einfacher Oberflächen immer noch so unreif ist, ist kaum überraschend
Wenn niemand genug Aufwand hineinsteckt, kann man nicht erwarten, dass es ausreift
Mehr Aufwand fließt in Web-Technologien, deshalb bleiben die Leute daran hängen. Man schaut auf nativ, sagt „nicht weit genug entwickelt“, und investiert dann wieder mehr in Webentwicklung; dieser Kreislauf wiederholt sich
Im Browser funktioniert vieles bereits „einfach so“, daher will kaum noch jemand den Aufwand treiben, nativ zu verbessern
Einer der Gründe, warum die Web-Seite viel ausgereifter ist, liegt darin, dass große kommerzielle OS-Hersteller nicht mit der Zeit gehen wollten. Die Windows-UI-Toolkits sind wirklich grauenhaft
Ich hatte in meiner AI-Chat-App fast genau dieselbe Erfahrung. Nichts funktioniert richtig
Markdown-Rendering ist langsam und ruckelig, Streaming ist langsam und ruckelig, und alles blockiert die UI
Ich habe mindestens fünf populäre Texteditor-Komponenten für UIKit und SwiftUI von GitHub ausprobiert, und alle waren auf die eine oder andere Weise kaputt, fehlerhaft oder langsam. Völlig absurd
Das ist ein schwieriges Problem. Ich habe ausführlich darüber geschrieben, wie ich es beim Bau eines Block-Editors von Grund auf mit Qt C++ und QML gelöst habe
Ich hatte ähnliche Probleme mit Auswahl zwischen nicht zusammenhängenden Blöcken, dem Anzeigen des Markdown-Quelltexts unter dem Cursor und unterschiedlichen Delegate-Größen
Auf Basis dessen, was ich damals gelernt habe, baue ich jetzt einen nativen LLM-Client mit einem Streaming-Markdown-Parser
[1] https://rubymamistvalove.com/block-editor
[2] https://www.get-vox.com
Lobste.rs-Kommentare
Electron ist im Grunde ein Wrapper um eine WebView, zieht aber die komplette Chromium-Engine mit, wodurch die App-Größe als Preis für die Bequemlichkeit viel zu stark anwächst
2001–2002 haben wir das ikonische Sprechblasen-Text-Layout von iChat mit
NSTextViewund allen möglichen Tricks umgesetzt, und selbst mit der Hilfe von Hideki Itamura, dem Text-Designer von AppKit, war das ziemlich mühsam. Heute ist es mit HTML+CSS recht einfachIch war an einer App beteiligt, die Tauri nutzte, und nachdem wir sie auf Electron mit Chromium umgestellt hatten, funktionierte sie deutlich besser. Besonders wichtig war dabei auch, dass wir einen sehr breiten Bereich von win7 bis win11 abdecken mussten
Bei Tauri & Co. wirkt es attraktiv, dass sie die System-WebView verwenden, aber unter Windows ist das dann Chrome oder Edge, unter macOS Safari und in anderen Umgebungen im Grunde Glückssache. Am Ende haben Vorhersehbarkeit und Reife gewonnen, und aus unbekannten Gründen war auch die Performance besser
Letztlich will ich bessere Software, statt
htop-Diagramme zufriedenzustellenDer Kern des Blogposts ist nicht „Alle sollten Electron wählen“, sondern dass ich jetzt verstehe, warum selbst Unternehmen mit Ressourcen und Geld weiterhin Electron oder Web-Technologien wählen. Zumindest nach meinem Maßstab liefert das mit den richtigen Kompromissen eine gute User Experience
Es gibt viele, die Apples TextKit 2 oder andere native Text-Frameworks verteidigen, aber es gibt kaum populäre und performante Texteditoren, die nur mit Apples SDKs gebaut wurden. Xcode macht das ziemlich gut und ist wohl fast der einzige Fall aus der Praxis. Zed, Sublime Text, Visual Studio Code und JetBrains-IDs nutzen alle aus gutem Grund eigene Lösungen für das Text-Rendering
Deshalb kann selbst etwas, das auf die schlechteste Weise gebaut wurde, in ihrer eigenen Umgebung okay aussehen
Für alle anderen, die Geräte mit deutlich geringerer Leistung nutzen, bleibt dann weiter aufgeblähte und langsame Software übrig
Der Autor scheint das hier allerdings nicht weiter erkundet zu haben
Von außen betrachtet wirkt Flutter wie eine Antwort auf die Frage „Was wäre, wenn man aus Chromium nur Skia als Renderer behält und es für GUI-Apps verwendet?“. Es müsste ein plattformübergreifendes Werkzeug sein, das leichter als Electron ist und dennoch ähnliche Fähigkeiten hat
contentEditable-DIV verwendet, und eine Unterklasse vonWKWebViewnutztDie Ironie ist, dass Apples native Text-Engine ein deutlich besseres Datenmodell verwendet als ein HTML-DOM-Baum, nämlich Strings und stilbezogene Attribute mit Run-Length-Encoding
Text im DOM zu bearbeiten ist fast ein Albtraum, weil Auswahlbereiche oft mehrere Elemente über mehrere Ebenen hinweg schneiden und deshalb sehr aufwendig aufgeteilt und wieder zusammengeführt werden müssen. Als ich damals zum ersten Mal einen Safari-Build mit Unterstützung für
contenteditablein die Finger bekam, habe ich Unmengen an Bug-Reports eingereicht, und noch heute gehen viele Web-Rich-Text-Editoren kaputt, wenn man Listeneinträge ausschneidet oder einfügtAm Ende scheint etwas Ähnliches passiert zu sein wie bei CISC gegen RISC in den 90er- und 00er-Jahren. Eine „unterlegene“ Struktur hat mehr Ressourcen erhalten und dadurch eine überlegene Implementierung hervorgebracht