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
220
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
24
動画エフェクトに関する新技術の紹介
shomakato
0
28
はじめてのPDFKit
shomakato
0
45
SwiftとC++を利用した画像処理プログラミング
shomakato
0
2.4k
Other Decks in Programming
See All in Programming
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
8
4.8k
さぁV100、メモリをお食べ・・・
nilpe
0
140
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
770
CSC307 Lecture 17
javiergs
PRO
0
320
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
690
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
170
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.3k
DynamoDBには集計系のクエリがないけどなんとかしたい
musan
1
140
New "Type" system on PicoRuby
pocke
1
930
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
500
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.6k
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
1
240
Featured
See All Featured
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
56k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
480
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
590
Accessibility Awareness
sabderemane
1
140
Documentation Writing (for coders)
carmenintech
77
5.4k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
470
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.2k
Done Done
chrislema
186
16k
sira's awesome portfolio website redesign presentation
elsirapls
0
280
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
380
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දࣔ ɹ- ϖʔδ൪߸ͷߋ৽