世界を動かす技術を、日本語で。

ネイティブな体験、テキストが必要になるまで

概要

  • macOS/iOSネイティブ開発者 として20年の経験を持つ筆者の体験談
  • SwiftUIやAppKit によるリッチテキスト・チャット実装の難しさ
  • WebKitやElectron の方が実用的な理由
  • ネイティブ開発の限界 と現代アプリの要件
  • Electron等の選択が合理的 である現状の指摘

ネイティブ開発者が感じるSwiftUI・AppKitの限界

  • Swift/SwiftUI でMarkdown対応チャットを実装しようとした体験談
  • シンプルな画面ではSwiftUIの パフォーマンスは十分、しかし複雑な処理では問題が顕在化
  • Markdownドキュメント全体の選択 がSwiftUIプリミティブでは不可能(設計上の制約)
  • NSTextView に切り替えるも、SwiftUIとの連携やテスト・パフォーマンス面での恩恵を失う
  • テキストストリーミング でCPUスパイク発生、パフォーマンス問題
  • AppKit/NSCollectionView に戻るも、セルのブリンク(ちらつき)が避けられない
  • TextKit 2 でプロトタイプ作成、パフォーマンスは許容範囲だがストリーミングは依然として非効率
  • SwiftUIを完全排除しAppKitに専念しても、 テキスト拡張処理 など手作業が増え、全体が壊れやすい
  • 基本的なmacOS機能(辞書検索、選択、アクセシビリティ等) の実装に膨大な工数が必要

WebKit・Electronの合理性と現代アプリの要件

  • WebKitでMarkdown描画 を試すと、パフォーマンス・タイポグラフィ・制御性が良好
  • Electron で簡単なプロジェクトを作成したところ、 テキスト操作やMarkdown描画が即動作
  • macOS統合 や高度なGit diff描画も数行で実現可能
  • TextKit 2の自作実装よりも高性能 で、必要な機能がほぼ「箱出し」で利用可能

なぜWebベースの選択が主流なのか

  • リッチテキスト・チャット や柔軟なタイポグラフィなど、現代アプリの主要UIパターンはWeb技術が得意
  • SwiftUIはシンプル画面やパフォーマンス重視部分には最適 だが、リッチテキストには不向き
  • ElectronやReact Native なら、ネイティブ連携を維持しつつ優れたテキストレンダリングが可能
  • もはや「クイックソリューション vs 本格ソリューション」の議論ではなく、 ネイティブSDKが制約となる時代
  • SwiftUIやApple純正SDK はリッチテキストチャットには現実的な選択肢ではない

結論

  • 現代のチャット・リッチテキストアプリ 開発にはWeb技術が不可欠
  • ネイティブ技術の強み が活かせる範囲は限定的
  • Electron等の選択は妥協ではなく合理的判断 となっている現状

Hackerたちの意見

自分のAIチャットアプリでもほぼ同じような経験をしたよ。何も上手くいかない。Markdownのレンダリングは遅いし、ラグもあるし、ストリーミングも遅くてラグがある。UIがロックアップすることも多い。GitHubでUIKitやSwiftUIの人気のテキストエディタコンポーネントを少なくとも5つ試してみたけど、どれも何かしら壊れてて、バグだらけで、遅かった。ほんと馬鹿げてる。

コード見せるか、さもなくば出て行ってもらうよ。今はMarkdownをレンダリングしたり、テキストをストリーミングしたりできるネイティブのMacやiOSアプリがたくさんあるから、こいつの言い訳が気になるね。

ウェブビューなし? コード見せてくれる?

OPは「SwiftUIのプリミティブから作られたMarkdownドキュメント全体を選択したい」と言ってるけど、誰がそんなことを望むの? どんな製品思考がそれを求めてるの?それってドキュメントエディタのように聞こえるけど、何十年も作るのが難しいものだし、LLMチャットUIには範囲外だよね。みんなは結局、連続したブロック内での選択だけをサポートして、全メッセージのコピー用ボタンを用意するって感じだよ。

2015年にジュニアエンジニアだった頃を思い出すな。iOSアプリ内で段落にクリック可能なリンクをレンダリングするように頼まれたんだ。Swiftがちょうどリリースされたばかりで、まだObjC/UIKitスタックしか使ってなかった。ほんと悪夢だった。なんとか動かすことができたけど、ギリギリだったよ。それ以降、2016年くらいからiOSにはほとんど触れてないから、新しいSwiftUIの機能にはこれが組み込まれてると思ってたんだけど、当然のことながらそうじゃなかった。ありえないよね。

Qtは10年前にこれをかなり簡単にしてくれたよ。

属性付きテキストはずっと前からこれをうまく扱ってると思ってたけど、そうじゃなかったの?

NSLinkAttributeName?

ほんとに「Link」って名前なんだよね。https://developer.apple.com/documentation/swiftui/link これ以上簡単にするのは無理なんじゃないかな。

iOSアプリの段落内でクリック可能なリンクをレンダリングするように求められた その具体的な要求自体がすでに悪いアイデアだった。

macOSを使ってるなら、WebKitはネイティブのOSフレームワークだよ。MarkdownをレンダリングするのにWebKitを使うのは全然適切だと思う。でも、もしすべてをWebKitでレンダリングしてるなら、それは馬鹿げてる。PDFKitで全部をレンダリングするのが馬鹿げてるのと同じようにね。でもMarkdownビューに関しては、WebKitは論理的な選択だと思う。後からテーブルをひっくり返して、すべてをChromiumのウェブアプリに置き換える必要はないよ。

でも、なんでWebKitを使ってリッチテキストをレンダリングすることを期待するの? HTML/CSS/JSレンダラーを使ってテキストをレンダリングするのが「完全に適切」なら、何が適切じゃないの? なんで全てをそれでレンダリングしないの?「テキストのレンダリングは完全に適切」って言いながら、「全てをレンダリングするのは馬鹿げてる」ってどういうことなのか理解できないよ。

Hacker Newsで議論の続きを見る