Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
はじめてのPDFKit.pdf
Search
shoma.kato
April 28, 2025
Programming
230
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
はじめてのPDFKit.pdf
shoma.kato
April 28, 2025
More Decks by shoma.kato
See All by shoma.kato
体験!SwiftChartsの世界
shomakato
0
26
動画エフェクトに関する新技術の紹介
shomakato
0
29
はじめてのPDFKit
shomakato
0
52
SwiftとC++を利用した画像処理プログラミング
shomakato
0
2.5k
Other Decks in Programming
See All in Programming
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
150
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
150
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
140
act2-costs.pdf
sumedhbala
0
120
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
340
信頼性について考えてみる(SRE NEXT 2026 miniLT)
hayama17
0
200
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
1
240
共通化で考えるべきは、実装より公開する型だった
codeegg
0
270
symfony/aiとlaravel/boost
77web
0
140
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
140
初めてのKubernetes 本番運用でハマった話
oku053
0
130
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
Featured
See All Featured
Building Applications with DynamoDB
mza
96
7.1k
Mobile First: as difficult as doing things right
swwweet
225
10k
Balancing Empowerment & Direction
lara
6
1.2k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Speed Design
sergeychernyshev
33
1.9k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
880
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
610
Bash Introduction
62gerente
615
220k
Making the Leap to Tech Lead
cromwellryan
135
10k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
We Have a Design System, Now What?
morganepeng
55
8.2k
Transcript
͡ΊͯͷPDFKit Ճ౻ਅ
2 גࣜձࣾZOZO Ճ౻ ਅ • X: @shoma10170806 • 20234݄: ZOZOೖࣾʢ3ʣ
• γϣοϓελοϑͷൢചαϙʔτπʔϧ ʮFAANSʯͷiOSΞϓϦΛ։ൃ • ത࢜ޙظ՝ఔʹࡏֶதɹը૾ॲཧͳͲͷݚڀʹैࣄ
3 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ཱͭใͷදࣔ - ֦େɾॖখ - ϖʔδ൪߸ͷදࣔ
4 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ཱͭใͷදࣔ - ֦େɾॖখ - ϖʔδ൪߸ͷදࣔ
5 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ཱͭใͷදࣔ - ֦େɾॖখ - ϖʔδ൪߸ͷදࣔ
6 FAANSͷ৽ػೳ PDFදࣔ: PDFKit ɾPDFͷදࣔػೳ - ཱͭใͷදࣔ - ֦େɾॖখ -
ϖʔδ൪߸ͷදࣔ
7 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
8 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
9 PDFDocumentͷಡΈࠐΈ Section1: PDFKitΛ༻͍ͨදࣔ extension URLSession { func data(with url:
URL) async throws -> (Data, URLResponse) { try await data(from: url) } } private func loadPdfDocument() async { var pdfDocument: PDFDocument? do { let (data, _) = try await URLSession.shared.data(with: pdfUrl) if let document = PDFDocument(data: data), document.pageCount > 0 { self.pdfDocument = document } } catch { // ಡΈࠐΈΤϥʔͷ߹ } }
private func loadPdfDocument() async { var pdfDocument: PDFDocument? do {
let (data, _) = try await URLSession.shared.data(with: pdfUrl) if let document = PDFDocument(data: data), document.pageCount > 0 { self.pdfDocument = document } } catch { // ಡΈࠐΈΤϥʔͷ߹ } } 10 PDFDocumentͷಡΈࠐΈ Section1: PDFKitΛ༻͍ͨදࣔ pdfUrl: https:// xxx.pdf extension URLSession { func data(with url: URL) async throws -> (Data, URLResponse) { try await data(from: url) } }
private func loadPdfDocument() async { var pdfDocument: PDFDocument? do {
let (data, _) = try await URLSession.shared.data(with: pdfUrl) if let document = PDFDocument(data: data), document.pageCount > 0 { self.pdfDocument = document } } catch { // ಡΈࠐΈΤϥʔͷ߹ } } extension URLSession { func data(with url: URL) async throws -> (Data, URLResponse) { try await data(from: url) } } 11 PDFDocumentͷಡΈࠐΈ Section1: PDFKitΛ༻͍ͨදࣔ ɾdata͔ΒPDFDocumentΛੜ ɾϖʔδ: 1Ҏ্
12 PDFͷදࣔ let pdfView = PDFView() pdfView.document = document pdfView.displayMode
= .singlePageContinuous pdfView.displayDirection = .vertical pdfView.autoScales = true pdfView.minScaleFactor = pdfView.scaleFactor ① PDFViewʹPDFDocumentͷૠೖ Section1: PDFKitΛ༻͍ͨදࣔ
13 PDFͷදࣔ ① PDFViewʹPDFDocumentͷૠೖ ② දࣔํ๏ͷઃఆ let pdfView = PDFView()
pdfView.document = document pdfView.displayMode = .singlePageContinuous pdfView.displayDirection = .vertical pdfView.autoScales = true pdfView.minScaleFactor = pdfView.scaleFactor Section1: PDFKitΛ༻͍ͨදࣔ
let pdfView = PDFView() pdfView.document = document pdfView.displayMode = .singlePageContinuous
pdfView.displayDirection = .vertical pdfView.autoScales = true pdfView.minScaleFactor = pdfView.scaleFactor 14 PDFͷදࣔ ① PDFViewʹPDFDocumentͷૠೖ ② දࣔํ๏ͷઃఆ ③ PDFͷαΠζΛࣗಈͰௐ Section1: PDFKitΛ༻͍ͨදࣔ
let pdfView = PDFView() pdfView.document = document pdfView.displayMode = .singlePageContinuous
pdfView.displayDirection = .vertical pdfView.autoScales = true pdfView.minScaleFactor = pdfView.scaleFactor 15 PDFͷදࣔ ① PDFViewʹPDFDocumentͷૠೖ ② දࣔํ๏ͷઃఆ ④ ॖখαΠζͷ࠷খͷܾఆ ③ PDFͷαΠζΛࣗಈͰௐ Section1: PDFKitΛ༻͍ͨදࣔ
let pdfView = PDFView() pdfView.document = document pdfView.displayMode = .singlePageContinuous
pdfView.displayDirection = .vertical pdfView.autoScales = true pdfView.minScaleFactor = pdfView.scaleFactor 16 PDFͷදࣔ ① PDFViewʹPDFDocumentͷૠೖ ② දࣔํ๏ͷઃఆ ④ ॖখαΠζͷ࠷খͷܾఆ ③ PDFͷαΠζΛࣗಈͰௐ Section1: PDFKitΛ༻͍ͨදࣔ
17 ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ ॳظදࣔʢζϨʣ ਖ਼ৗ ζϨ Section1: PDFKitΛ༻͍ͨදࣔ
18 ζϨ ɾζϨͷݪҼ - PDFͷαΠζ - தԝἧ͑ Section1: PDFKitΛ༻͍ͨදࣔ ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ
ਖ਼ৗ ॳظදࣔʢζϨʣ
19 ζϨ ɾζϨͷݪҼ - PDFͷαΠζ - தԝἧ͑ Section1: PDFKitΛ༻͍ͨදࣔ ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ
ॳظঢ়ଶ: PDFࠨ্͕ը໘ ਖ਼ৗ ॳظදࣔʢζϨʣ
20 ζϨͷվળํ๏ if let firstPage = document.page(at: 0) { pdfView.go(
to: firstPage.bounds(for: pdfView.displayBox), on: firstPage ) } Section1: PDFKitΛ༻͍ͨදࣔ
21 if let firstPage = document.page(at: 0) { pdfView.go( to:
firstPage.bounds(for: pdfView.displayBox), on: firstPage ) } ① PDFDocumentͷ1ϖʔδΛऔಘ ② 1ϖʔδͷࠨ্͕දࣔ͞ΕΔΑ͏ʹҠಈ Section1: PDFKitΛ༻͍ͨදࣔ ζϨͷվળํ๏
22 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
23 ϖʔδ൪߸ͷදࣔ ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ
24 ϖʔδ൪߸ͷऔಘํ๏ let document: PDFDocument? let pdfView = PDFView() let
totalPage = document.pageCount NotificationCenter.default .addObserver(forName: .PDFViewPageChanged, object: pdfView, queue: .main) { _ in Task { @MainActor in let pageNumber = pdfView.currentPage?.pageRef?.pageNumber } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ
25 ϖʔδ൪߸ͷऔಘํ๏ let document: PDFDocument? let pdfView = PDFView() let
totalPage = document.pageCount NotificationCenter.default .addObserver(forName: .PDFViewPageChanged, object: pdfView, queue: .main) { _ in Task { @MainActor in let pageNumber = pdfView.currentPage?.pageRef?.pageNumber } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ ② ϖʔδͷมߋࢹɾ൪߸औಘ
26 ϖʔδ൪߸ͷऔಘํ๏ let document: PDFDocument? let pdfView = PDFView() let
totalPage = document.pageCount NotificationCenter.default .addObserver(forName: .PDFViewPageChanged, object: pdfView, queue: .main) { _ in Task { @MainActor in let pageNumber = pdfView.currentPage?.pageRef?.pageNumber } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ ② ϖʔδͷมߋࢹɾ൪߸औಘ
27 ϖʔδ൪߸औಘͷ ɾԣͷPDF - ը໘্ʹෳຕͷPDF - ϖʔδ൪߸: 2͔Βදࣔ͞ΕΔ ॳظঢ়ଶ: ϖʔδ൪߸Λ1ʹ͢Δ
※ Πϝʔδը૾
28 ॳظঢ়ଶͷఆํ๏ ɾoffset͕0: ϖʔδ൪߸1 PDFView: offsetऔಘͰ͖ͳ͍
29 ॳظঢ়ଶͷఆํ๏ UIScrollView extension PDFView { func scrollView() -> UIScrollView?
{ return self.subviews.compactMap { $0 as? UIScrollView }.first } } ɾoffset͕0: ϖʔδ൪߸1 PDFView: offsetऔಘͰ͖ͳ͍ ϫʔΫΞϥϯυ
30 ॳظঢ়ଶͷఆํ๏ if let scrollView = pdfView.scrollView() { scrollView.publisher(for: \.contentOffset)
.sink { [weak pdfView] contentOffset in Task { @MainActor in guard let pdfView = pdfView else { return } if contentOffset.y <= 0.0 { currentPage = 1 } else if let pageNumber = pdfView.currentPage?.pageRef?.pageNumber, pageNumber != currentPage { NotificationCenter.default.post( name: .PDFViewPageChanged, object: pdfView ) } } } } ① UIScrollViewͷݕग़ ② offSetͷpublisherΛൃߦ
if let scrollView = pdfView.scrollView() { scrollView.publisher(for: \.contentOffset) .sink {
[weak pdfView] contentOffset in Task { @MainActor in guard let pdfView = pdfView else { return } if contentOffset.y <= 0.0 { currentPage = 1 } else if let pageNumber = pdfView.currentPage?.pageRef?.pageNumber, pageNumber != currentPage { NotificationCenter.default.post( name: .PDFViewPageChanged, object: pdfView ) } } } } 31 ॳظঢ়ଶͷఆํ๏ ③ ϖʔδ൪߸ͷߋ৽ ① UIScrollViewͷݕग़ ② offSetͷpublisherΛൃߦ
if let scrollView = pdfView.scrollView() { scrollView.publisher(for: \.contentOffset) .sink {
[weak pdfView] contentOffset in Task { @MainActor in guard let pdfView = pdfView else { return } if contentOffset.y <= 0.0 { currentPage = 1 } else if let pageNumber = pdfView.currentPage?.pageRef?.pageNumber, pageNumber != currentPage { NotificationCenter.default.post( name: .PDFViewPageChanged, object: pdfView ) } } } } 32 ॳظঢ়ଶͷఆํ๏ ③ ϖʔδ൪߸ͷߋ৽ ① UIScrollViewͷݕग़ ② offSetͷpublisherΛൃߦ
if let scrollView = pdfView.scrollView() { scrollView.publisher(for: \.contentOffset) .sink {
[weak pdfView] contentOffset in Task { @MainActor in guard let pdfView = pdfView else { return } if contentOffset.y <= 0.0 { currentPage = 1 } else if let pageNumber = pdfView.currentPage?.pageRef?.pageNumber, pageNumber != currentPage { NotificationCenter.default.post( name: .PDFViewPageChanged, object: pdfView ) } } } } 33 ॳظঢ়ଶͷఆํ๏ ③ ϖʔδ൪߸ͷߋ৽ ① UIScrollViewͷݕग़ ② offSetͷpublisherΛൃߦ
34 ϖʔδ൪߸ͷදࣔ݁Ռ ※දࣔ͞Ε͍ͯΔPDFΠϝʔδͰ͢
35 ·ͱΊ ɾPDFKitͷ͍ํ ɹ- PDFKitΛ༻͍ͨPDFදࣔ ɹ- ϖʔδ൪߸ͷߋ৽