---
title: "Bookilで漫画の見開きをページ送りで読ませたくて描画を作り直している"
description: "iOS の PDFKit は「ページ送り」と「見開き表示」を同時に成立させられません。書籍リーダー Bookil で見開きの読み心地を作りたかった結果、描画層を自前で持つ方針に振って今もその開発を進めています。PDFKit の制約と、判断の軸を扱います。"
category: "Apple"
tags: ["iOS","PDFKit","Bookil","Swift","書籍リーダー"]
publishedAt: "2026-06-25"
lastmod: "2026-07-24"
---

書籍リーダー [Bookil](https://bookil.labee.dev/) では、漫画や技術書のページを「めくる感覚」と「見開きの並び」の両方で読ませたい。iOS 標準の [PDFKit](https://developer.apple.com/documentation/pdfkit) は片方ずつなら出せますが、両方を同時に成立させられません。妥協案を順に検討した結果、PDFKit の上に乗りきらず、描画層を自前に切り出して育てる方針に振りました。現在もその開発を進めている途中です。

::card[https://bookil.labee.dev/]

この記事では PDFKit の `displayMode` と `usePageViewController` を組み合わせると何が成立しないか、検討した妥協案、そして自前の描画層に振り直した判断の軸を順に扱います。

## 書籍リーダーで「ページ送り×見開き」を落としたくなかった

Bookil は iOS / iPadOS で PDF や EPUB を読むためのアプリケーションです。技術書、漫画、雑誌、論文といった「書籍の形をしたコンテンツ」を、紙の本に近い感覚でめくれる状態にするのが目標です。

書籍を読む体験には、書籍タイプごとに必要な要素があります。漫画の見開きカットは、左右ページが同じ視野に並んでこそ成立します。技術書の図版は見開きいっぱいに広がる構成が前提のことがあります。とはいえ、紙の本らしさを支えているのはページをめくる動作です。Bookil ではスクロールで連続的に流れていく読書体験と、1ページ単位でスナップする読書体験を、別物として設計します。

落としたくなかったのは次の3点です。

- 1ページ単位でスナップするページ送りで、紙の本のリズムを残す
- 漫画と技術書のために、左右2ページを同じ視野に並べる見開き表示を成立させる
- 右綴じと左綴じ、縦書きと横書きを書籍メタデータから切り替える

この3点のうち、最初の2点が PDFKit の標準機能では同時に成立しません。

## PDFKit の `displayMode` を整理する

`PDFView` の [`displayMode`](https://developer.apple.com/documentation/pdfkit/pdfdisplaymode) には4つの選択肢があります。

| モード | 挙動 |
|---|---|
| `singlePage` | 1ページずつ表示。ページ移動は手動操作 |
| `singlePageContinuous` | 1ページ幅で縦に連続スクロール |
| `twoUp` | 2ページ並びを表示。スプレッド単位で手動切り替え |
| `twoUpContinuous` | 2ページ並びを連続スクロール |

これに加えて、[`usePageViewController(_:withViewOptions:)`](https://developer.apple.com/documentation/pdfkit/pdfview/usepageviewcontroller(_:withviewoptions:)) を有効にすると、内部で `UIPageViewController` が動き、横方向のスワイプでページがスナップします。紙の本をめくる感覚に最も近い挙動です。

組み合わせは一見すると4×2で8通りに見えます。実際にはそうなりません。`usePageViewController` を有効にしたとき、内部のレイアウトは1ページずつのスナップ送りに固定されます。`displayMode` に `.twoUp` を指定しても、見開き並びとページ送りスナップは同時には成立しません。

逆に、`.twoUp` 単体で見開き表示にすると、見開き単位の手動切り替えは行えますが、ページ送りのスナップ挙動やめくりアニメーションは提供されません。スワイプ操作やジェスチャーはすべて自前で書きます。

## 妥協案を3つ並べた

描画層を自前で持つコストは小さくありません。判断の前に、PDFKit の範囲でどこまで耐えられるかを順に検討しました。

### 案A `.singlePage` + `usePageViewController`

ページ送りのスナップ感は得られます。一方で見開きは成立しません。漫画の見開きカットは左右に分断され、技術書の見開き図版も同様です。書籍タイプによってはコンテンツの読み方そのものが崩れます。

### 案B `.twoUpContinuous`

見開き並びで連続スクロールするモードです。図版は割れず、2ページ分の情報量が常に視野に入ります。ただし、紙の本をめくる感覚は失われます。スクロール量と「現在のページ」の対応がぼやけ、しおりや読書進捗の指標が連続値になります。漫画のように1見開きごとに視線をリセットする読み方では、連続スクロールが読書のリズムを壊します。

### 案C `.twoUp` + 自前ジェスチャー

スプレッド単位の手動切り替えに、自前のスワイプジェスチャーを足す案です。見開きとページ送りの両立はできそうに見えます。しかし `usePageViewController` が暗黙に提供しているページ間アニメーション、エッジでのバウンス、ジェスチャーの中断と復帰、慣性スクロールの調整といった細部を、すべて一から書き直します。

案Cまで踏み込むと、PDFKit の表示パイプラインだけ借りて、操作系を全部書き直す状態に近くなります。PDFKit 本体の抽象に乗っているメリットが薄れていきます。

3案とも、書籍リーダーのコア UX のどちらかを諦めるか、PDFKit の抽象に上塗りで継ぎ足す形になりました。書籍タイプによってはコンテンツが破綻するため、製品として選びにくい結論です。

![表示が単ページか見開きか、送りがスナップか連続スクロールかで4通りのマスを作ると、単ページとスナップの組み合わせは案Aの.singlePageとusePageViewControllerで成立し、単ページと連続は.singlePageContinuous、見開きと連続は案Bの.twoUpContinuousで成立する。ところが見開きとスナップ送りのマスだけが空いている。usePageViewControllerを有効にすると内部レイアウトが1ページ送りに固定されるためで、案Cはここを自前のジェスチャーで埋める案にあたる](/images/posts/bookil-custom-pdf-renderer/pdfkit-matrix.svg)

## 自前の描画層に振った3つの判断軸

最終的に Bookil では、PDF のデコード自体は標準の土台に任せ、ページの描画と並び方とめくり方の制御を自前の層で持つ設計に振りました。実装の具体は非公開ですが、判断の軸は次の3点に整理されます。

1つ目は、書籍リーダーの中心 UX である「ページ送り×見開き」は妥協項目にできない、と判断したことです。Bookil で対象にしている書籍タイプには、漫画と技術書が含まれます。どちらも見開きの設計が崩れた瞬間にコンテンツの読み方が変わります。ここを連続スクロールやページ分断で代替する選択肢は、書籍リーダーとしての出発点を否定する形になります。

2つ目は、PDFKit の `displayMode` が書籍タイプの幅に対して粒度が粗すぎる点です。Bookil では右綴じの漫画、左綴じの技術書、1ページ目を単独で扱う雑誌、奇数ページから始まる章扉といった構成を扱います。書籍メタデータから読み方を組み立てるには、4択フラグでは表現しきれない領域があります。

3つ目は、抱え込む領域を限定できると見立てたことです。PDF の仕様は広大で、フォント埋め込み、注釈、リンク、フォーム、トランスペアレンシ、暗号化された PDF といった機能がぶら下がります。これを全部自前で持つのは現実的ではありません。デコードと描画の土台は標準フレームワークに任せ、ページの並び方とめくり方の制御だけを自前の層に切り出す方針なら、保守する境界線を引けます。

この3点が揃ったため、書籍リーダーのコア UX に合わせて土台を作り直す判断に踏み切りました。

## いまどこまで動いているか

描画層は現在も育てている途中で、右綴じ漫画と縦書き / 横書き混在の書籍タイプで「めくる」「並べる」「進む」のリズムが形になってきています。PDFKit に乗っていた時代に出せていた読書体験は概ね再現できる状態まで来ており、いまは細かい挙動の差分を一つずつ詰める段階です。新しい土台に乗せ替えたぶんだけ、めくり始めの当たり判定や最終ページの折り返しといった細部にバグが出やすく、ここを念入りに確認しています。書籍メタデータからの読み方切り替えも実装が進んでいます。

::card[https://apps.apple.com/app/bookil/id6475175265]

## 標準フレームワークと自前のラインをどこに引くか

標準フレームワークを使うべきか、自前で作るべきか、という問いに一般解はありません。判断の軸は、製品のコア UX が標準の抽象でどこまで成立するか、という1点に集約されます。

PDFKit は、PDF ビューアとして広い領域をカバーします。注釈、検索、リンク追従、フォーム入力、暗号化された PDF の扱いまで含めて、汎用の PDF ビューアを作るなら土台として申し分ありません。それでも、PDFKit が想定している読み方は「ドキュメントを読む」読み方です。書籍を読むための「めくる」「並べる」「進む」のリズムは、PDFKit の抽象の外側にあります。

Bookil のケースでは、汎用ビューアと書籍リーダーのズレが、`usePageViewController` と `.twoUp` の組み合わせ問題として表面化しました。標準フレームワークの制約に合わせて体験を曲げるより、体験に合わせて土台を作り直すほうが、長期で見て選びやすい道だ、という判断で今のところ進めています。