← Back to Blogs
HN Story

Native All the Way, Until You Need Text: The Struggle of Rich Text Rendering

May 19, 2026

Native All the Way, Until You Need Text: The Struggle of Rich Text Rendering

For nearly two decades, the mantra for Apple platform developers has been "native all the way." The promise is simple: better performance, deeper OS integration, and a superior user experience. However, as modern application patterns shift toward chat-heavy interfaces and LLM-driven streaming text, a frustrating reality is emerging. For many, the native path leads not to a polished product, but to a technical dead end.

In a recent provocative piece, developer Artem Loenko details his struggle to implement a simple chat interface with Markdown support in SwiftUI. What should have been a trivial task became a descent through the layers of Apple's SDKs, revealing a surprising lack of maturity in native text handling for complex, dynamic content.

The Native Descent: From SwiftUI to TextKit

Loenko's journey began with SwiftUI, the modern declarative framework. While capable of handling simple screens, he found that once he stepped into the realm of rich text and long-form scrolling, the experience degraded. The primary breaking point? The inability to select a whole Markdown document built from SwiftUI primitives—a basic user expectation that is simply not supported by design.

Seeking a more robust solution, he moved to NSTextView and TextKit 2. While these offered more control, they introduced new frictions:

  • Integration Gaps: TextKit 2 does not play well with the modern SwiftUI ecosystem, forcing a trade-off between performance testing and text functionality.
  • Performance Spikes: Streaming text (a requirement for any modern AI chat app) caused significant CPU spikes.
  • UI Glitches: Switching to NSCollectionView to solve performance issues resulted in "blinking" cells, another design-level constraint.

Ultimately, Loenko found that reaching feature parity with basic macOS behavior—context menus, dictionary lookups, and accessibility—would take months of manual labor. The conclusion was startling: the native tools designed to make development easier were actually becoming constraints.

The "Dark Side" and the Browser's Triumph

Driven to desperation, Loenko turned to WebKit and eventually Electron. The result was an immediate resolution of the problems that had plagued his native implementation. Text operations, Markdown rendering, and typography worked out of the box with performance that surpassed his pure TextKit 2 prototype.

This transition highlights a broader industry trend. Many of the most successful chat-heavy apps today are web-based because the browser engine is, quite simply, the most mature text rendering engine in existence. As one commenter, @StilesCrisis, noted:

"We take so much for granted in the modern WebKit/Blink stack. Modern multilingual text processing is a genuinely hard problem."

The Great Debate: Skills Issue or Systemic Failure?

The community reaction to Loenko's experience was polarized, reflecting a deep divide in the developer community.

The "Skills Issue" Argument

Some developers argued that native tools are sufficient if used correctly. @lenkite pointed to existing libraries like swift-markdown-ui as proof that Markdown rendering in SwiftUI is possible. Others, like @msephton, shared success stories of building highly performant text editors using TextKit 2, claiming that rapid keystrokes and full restyling can be achieved in under 8ms.

The Systemic Failure Argument

Conversely, many developers echoed Loenko's pain. @splittydev reported similar struggles with AI chat apps, noting that most popular GitHub components for UIKit/SwiftUI were "broken in one way or another, buggy, and slow."

There is also the argument that the web's dominance is a result of massive investment. @Yokohiii observed that Chrome is likely the "best funded software in the world," and its maturity is a result of immense financial and engineering effort that native frameworks simply haven't matched in the text-rendering space.

Synthesis: Finding the Middle Ground

The discussion suggests that the choice isn't necessarily a binary between "Pure Native" and "Full Electron." Several hybrid strategies emerged as viable alternatives:

  1. The Hybrid Approach: Use native frameworks for the application shell (menus, toolbars, navigation) and a WKWebView specifically for the rich text/Markdown areas. This leverages the browser's rendering power without sacrificing the overall native feel.
  2. Low-Level Customization: For those who cannot afford the overhead of a browser, building a custom layout engine (perhaps in Rust or C++) may be the only way to achieve publishing-grade performance.
  3. Accepting the Trade-off: Acknowledging that while Electron may be "bloated," it provides a level of productivity and text-handling reliability that is currently unmatched by Apple's high-level frameworks.

Conclusion

Text is deceptively simple. We interact with it every second of every day, yet rendering it dynamically, accessibly, and performantly is one of the hardest problems in software engineering. While SwiftUI and AppKit remain powerful for many use cases, the "native all the way" approach may be a liability when your app's primary value proposition is rich, flexible, and streaming text.

References

HN Stories