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
Search
shoma.kato
February 10, 2025
Technology
55
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
はじめてのPDFKit
PDFKitに関して様々なTipsを紹介します
shoma.kato
February 10, 2025
More Decks by shoma.kato
See All by shoma.kato
体験!SwiftChartsの世界
shomakato
0
27
動画エフェクトに関する新技術の紹介
shomakato
0
30
はじめてのPDFKit.pdf
shomakato
0
240
SwiftとC++を利用した画像処理プログラミング
shomakato
0
2.5k
Other Decks in Technology
See All in Technology
Software Supply Chain Attackからクラウド環境を守るためにできること
lhazy
2
250
ガバメントクラウドでのランサムウェア対策
techniczna
2
1.2k
ラジオの科学
frievea
0
300
モノリス Rails でも日中に rails db:migrate を走らせたい! / Daytime rails db:migrate on Monolithic Rails!
euglena1215
4
580
[ChatGPT Work LT]事務作業が苦手な人のための バックオフィスの「半」自動化
chimaki_iot
0
280
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
19k
つくって納得、つかって実感! 大規模言語モデルことはじめ ver2.0
recruitengineers
PRO
4
1.6k
Flutterをカメラで動かしたかった話
sony
1
140
認知負荷をGemini で溶かす — GKE 基盤「Orbit」における AI エージェントの実践
sansantech
PRO
1
290
侵入は突然に 〜 IoTマルウェアと悪用される家庭の機器 ~ / When Intrusion Strikes: IoT Malware and the Abuse of Home Devices
nttcom
0
1.6k
Model Studio CLI × Token Plan
maigo999
0
170
20260608_Codexの可能性_ノンプログラマー向け_大城追記
doradora09
PRO
0
800
Featured
See All Featured
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
380
The Curious Case for Waylosing
cassininazir
1
450
Abbi's Birthday
coloredviolet
3
9.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
67k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
430
Transcript
Copyright © ZOZO, Inc. ͡ΊͯͷPDFKit גࣜձࣾZOZO ϒϥϯυιϦϡʔγϣϯ։ൃຊ෦ FAANS෦ ϑϩϯτΤϯυϒϩοΫ Ճ౻
ਅ @shoma10170806
© ZOZO, Inc. 2 גࣜձࣾZOZO ϒϥϯυιϦϡʔγϣϯ։ൃຊ෦ FAANS෦ ϑϩϯτΤϯυϒϩοΫ Ճ౻ ਅ
• X: @shoma10170806 • 20234݄: ZOZOೖࣾʢ2ʣ • γϣοϓελοϑͷൢചαϙʔτπʔϧ ʮFAANSʯͷiOSΞϓϦΛ։ൃ • ത࢜ޙظ՝ఔʹࡏֶதɹը૾ॲཧͳͲͷݚڀʹैࣄ
© ZOZO, Inc. 3 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ίʔσΟωʔτͷߘʹཱͭใ - ֦େɾॖখ
- ϖʔδ൪߸ͷදࣔ
© ZOZO, Inc. 4 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ίʔσΟωʔτͷߘʹཱͭใ - ֦େɾॖখ
- ϖʔδ൪߸ͷදࣔ
© ZOZO, Inc. 5 FAANSͷ৽ػೳ ɾPDFͷදࣔػೳ - ίʔσΟωʔτͷߘʹཱͭใ - ֦େɾॖখ
- ϖʔδ൪߸ͷදࣔ
© ZOZO, Inc. 6 FAANSͷ৽ػೳ PDFදࣔ: PDFKit ɾPDFͷදࣔػೳ - ίʔσΟωʔτͷߘʹཱͭใ
- ֦େɾॖখ - ϖʔδ൪߸ͷදࣔ
© ZOZO, Inc. 7 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
© ZOZO, Inc. 8 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
© ZOZO, Inc. 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 { // ಡΈࠐΈΤϥʔͷ߹ } }
© ZOZO, Inc. 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) } }
© ZOZO, Inc. 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Ҏ্
© ZOZO, Inc. 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Λ༻͍ͨදࣔ
© ZOZO, Inc. 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Λ༻͍ͨදࣔ
© ZOZO, Inc. 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Λ༻͍ͨදࣔ
© ZOZO, Inc. 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Λ༻͍ͨදࣔ
© ZOZO, Inc. 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Λ༻͍ͨදࣔ
© ZOZO, Inc. 17 ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ ॳظදࣔʢζϨʣ ਖ਼ৗ ζϨ Section1: PDFKitΛ༻͍ͨදࣔ
© ZOZO, Inc. 18 ζϨ ɾζϨͷݪҼ - PDFͷαΠζ - தԝἧ͑
Section1: PDFKitΛ༻͍ͨදࣔ ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ ਖ਼ৗ ॳظදࣔʢζϨʣ
© ZOZO, Inc. 19 ζϨ ɾζϨͷݪҼ - PDFͷαΠζ - தԝἧ͑
Section1: PDFKitΛ༻͍ͨදࣔ ॳظঢ়ଶʹ͓͚ΔPDFදࣔҐஔͷζϨ ॳظঢ়ଶ: PDFࠨ্͕ը໘ ਖ਼ৗ ॳظදࣔʢζϨʣ
© ZOZO, Inc. 20 ζϨͷվળํ๏ if let firstPage = document.page(at:
0) { pdfView.go( to: firstPage.bounds(for: pdfView.displayBox), on: firstPage ) } Section1: PDFKitΛ༻͍ͨදࣔ
© ZOZO, Inc. 21 if let firstPage = document.page(at: 0)
{ pdfView.go( to: firstPage.bounds(for: pdfView.displayBox), on: firstPage ) } ① PDFDocumentͷ1ϖʔδΛऔಘ ② 1ϖʔδͷࠨ্͕දࣔ͞ΕΔΑ͏ʹҠಈ Section1: PDFKitΛ༻͍ͨදࣔ ζϨͷվળํ๏
© ZOZO, Inc. 22 Section1: PDFKitΛ༻͍ͨදࣔ Section2: ϖʔδ൪߸ͷߋ৽
© ZOZO, Inc. 23 ϖʔδ൪߸ͷදࣔ ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ
© ZOZO, Inc. 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 } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ
© ZOZO, Inc. 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 } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ ② ϖʔδͷมߋࢹɾ൪߸औಘ
© ZOZO, Inc. 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 } } ࠨଆ: ݱࡏͷϖʔδ൪߸ ӈଆ: ૯ϖʔδ ① ૯ϖʔδͷऔಘ ② ϖʔδͷมߋࢹɾ൪߸औಘ
© ZOZO, Inc. 27 ϖʔδ൪߸औಘͷ ɾԣͷPDF - ը໘্ʹෳຕͷPDF - ϖʔδ൪߸:
2͔Βදࣔ͞ΕΔ ॳظঢ়ଶ: ϖʔδ൪߸Λ1ʹ͢Δ ※ Πϝʔδը૾
© ZOZO, Inc. 28 ॳظঢ়ଶͷఆํ๏ ɾoffset͕0: ϖʔδ൪߸1 PDFView: offsetऔಘͰ͖ͳ͍
© ZOZO, Inc. 29 ॳظঢ়ଶͷఆํ๏ UIScrollView extension PDFView { func
scrollView() -> UIScrollView? { return self.subviews.compactMap { $0 as? UIScrollView }.first } } ɾoffset͕0: ϖʔδ൪߸1 PDFView: offsetऔಘͰ͖ͳ͍ ϫʔΫΞϥϯυ
© ZOZO, Inc. 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Λൃߦ
© ZOZO, Inc. 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Λൃߦ
© ZOZO, Inc. 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Λൃߦ
© ZOZO, Inc. 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Λൃߦ
© ZOZO, Inc. 34 ϖʔδ൪߸ͷදࣔ݁Ռ ※දࣔ͞Ε͍ͯΔPDFΠϝʔδͰ͢
© ZOZO, Inc. 35 ·ͱΊ ɾPDFKitͷ͍ํ ɹ- PDFKitΛ༻͍ͨPDFදࣔ ɹ- ϖʔδ൪߸ͷߋ৽
None