🦿
[iOS swift] PDFのレンダリング
iOSでPDFを表示する方法がわからなかったので調べた記録です。検索の足掛かりにしていただければ幸いです。
画像としてPDFのページを取得する
- CoreGraphicsをそのまま叩く
- PDFKitのPDFThumbnailViewを使用する (PDFの画像だけを欲しい場合はこれが一番手軽)
操作可能なViewとしてレンダリングする
- PDFKitのPDFViewを使用する
PDFKitは裏でCoreGraphicsを叩いている(色々便利にしてくれるラッパライブラリ)のでどこまで低レベルのAPIを叩くかの違い。
それぞれの特徴
アプローチ | 方式 | ズームの可否 | 描画速度 |
---|---|---|---|
CoreGraphics | CGContextに直接描画 | 不可(描画範囲を指定して再描画) | 速い |
PDFKit Thumbnail | UIImageとして取得 | 不可(描画範囲を指定して再取得) | 速い |
PDFView | UIViewとして取得 | 可 | 動的(読み込み中は低解像度のサムネイルが差し込まれる) |
CoreGraphicsやPDFKit ThumbnailはPDFはあくまでページを画像(ベクターではない)として取得しているだけなので、ズームをすると荒れます。ズームに応じて該当部分のみを取得し直しレンダリングすることで綺麗に表示できますがほとんどの場合PDFViewを使った方が良いでしょう。
アプローチ | テキスト選択 | ドキュメント | iOS Ver |
---|---|---|---|
CoreGraphics | 不可(自前の実装が必要) | https://developer.apple.com/documentation/coregraphics/cgpdfdocument | iOS 2.0+ |
PDFKit Thumbnail | 不可(ただのUIImage) | https://developer.apple.com/documentation/pdfkit/pdfview | iOS 11.0+ |
PDFView | 可(PDFKitが管理) | https://developer.apple.com/documentation/pdfkit/pdfthumbnailview | iOS 11.0+ |
テキストを選択させたい場合はPDFViewを使うと良いと思います。
PDFKit搭乗前は下記のようなライブラリが利用されていた...ぽいです。
また、i文庫HDなどのような初期からあるPDFリーダーアプリではテキストの選択を自前で処理していたようです。
- SafariのようにPDFをScrollViewで表示したいだけ
- PDFKitを利用
- PDFのページ画像が欲しいだけ(サムネイルを取得したいときなど)
- PDFKitのPDFThumbnailViewで欲しいサイズのサムネイルをUIImageとして取得する
- テキストを選択できるようにしたい
- PDFKitを利用
動作するサンプルコード (Playground)
CoreGraphics
PDFThumbnailView
import PlaygroundSupport
import UIKit
import PDFKit
guard let url = URL(string: "https://www.ci.seikei.ac.jp/yamamoto/lecture/automaton/text.pdf") else { fatalError() }
guard let doc = PDFDocument(url: url) else { fatalError() }
guard let page = doc.page(at: 0) else { fatalError() }
let image = page.thumbnail(of: CGSize(width: 1000, height: 1000), for: PDFDisplayBox.trimBox)
let view = UIImageView(image: image)
view.backgroundColor = UIColor.systemGray
view.contentMode = .scaleAspectFit
PlaygroundPage.current.liveView = view
PDFView
import PlaygroundSupport
import UIKit
import PDFKit
guard let url = URL(string: "https://www.ci.seikei.ac.jp/yamamoto/lecture/automaton/text.pdf") else { fatalError() }
guard let doc = PDFDocument(url: url) else { fatalError() }
let view = PDFView()
view.document = doc
PlaygroundPage.current.liveView = view
Discussion