Kristopher Baker iOSを土台に · プロダクトシステム · AI支援ワークフロー
← Aoede

shipped · 2026.06.12 · 約3分

本の中を探す、ライブラリ全体を探す

Aoedeで本は読めても、その中を検索することはできませんでした。いまはリーダーで⌘F(またはツールバーのボタン)を押すと、細い検索バーが開きます。入力すると「n / m」が出て、マッチを順に送って、終わったら閉じます。Macでは⌘Gと⇧⌘Gで次・前へ送り、Escで閉じます。ヒットした箇所にはどれも読み上げハイライトの下に寒色系の下線が付き(いま喋っている単語の色が優先)、現在のヒットは少し強く描かれます。ヒットをタップすると、そこから読み始めます。検索が自分で再生位置を動かすことはありません。スクロールするだけなので、声はそのまま進めながら先を見られます。

検索はライブラリ全体にも広げました。本の一覧が検索可能になり、クエリを入れると一覧が本ごとにまとまった結果に切り替わって、各スニペットでマッチした語句が強調されます。タップすると、その本のその文から開きます。裏側にあるのは SQLite の文単位のインデックスで、正規化したカラムを LIKE でスキャンしています。全文検索(FTS)はあえて使いませんでした。FTS には最小トークン長があって短いクエリが黙って落ちるのですが、日本語で検索したいものの多くは一文字か二文字です。素朴な正規化済みの LIKE なら、英語でも日本語でも長さに関係なく同じように効きます。正規化では大文字小文字・全半角・アクセントは畳みますが、仮名の違いは残します。日本語ではその違いはノイズではなく意味だからです。インデックスができる前に取り込んだ本は、起動時に一度だけバックフィルされます。

いちばん時間を食ったのは検索そのものではなく、検索が連れて行く先でした。長い本の終盤のヒットへ飛ぶと、以前はそこまでの道のりを全部アニメーションしていました。まだ描画もされていない中身を猛スピードで通り過ぎる、方向感覚を失うようなスクロールで、しかもスクロールは見つからない行を追いかけて見当違いのところに着地していました。いまは長いジャンプはターゲットに直接スナップします(プラットフォームによって、だいたい10〜14セグメントより遠ければ)。近いジャンプはこれまでどおり滑らかに動きます。「直接」を本当に「正しい行に」着地させるまでには何度か作り直しが要って、最終的には、ターゲットの行がレイアウトされた瞬間に自分の実際の位置を報告し、スクロールが推定の行の高さで当てずっぽうをする代わりに、そこへぴったり補正する形になりました。