Edited at

【PDFKit】Swiftでプレゼン資料を作る

More than 1 year has passed since last update.

この記事は リクルートライフスタイル Advent Calendar 2017 の3日目の記事です。


はじめに

ホットペッパービューティーでアプリの開発を担当してる@sotozakiです。

最近は資料を作る機会も増えてきました。

iOSエンジニアだったら、普段書いてるSwiftでプレゼン資料も作りたいはず(?)

今回はSwiftでプレゼン資料を作ってみます!


環境

バージョン

Swift
4.0

Xcode
9.1


完成したもの

output.jpg

このようなPDFの資料を作ることが出来ます。


プレゼン資料の作り方

PDFKitを使ってPDFを出力することでプレゼン資料を作ります。

今年のWWDCでもPDFKitが取り上げられ、MacOSのみだったものがiOSにも対応しました。


PDFKit

PDFKitのPDFViewというClassを利用することでPDFViewerのようなアプリは簡単に実装することができるようになりました。

今回はViewerではなくプレゼン資料としてPDFを出力したいため、PDFDocument, PDFPageといたClassを利用していきます。

Screen Shot 2017-11-12 at 10.19.46.png

https://devstreaming-cdn.apple.com/videos/wwdc/2017/241iivj8rn2fo3ft0r/241/241_introducing_pdfkit_on_ios.pdf


PDFDocument, PDFPage

Swift PlayGroundで書いていきます。

まずはPDFKitをimportします。

import PDFKit

PDFPageを継承したクラスを作成し、iOSエンジニア(の一部)には馴染みのあるdrawメソッドをoverrideして文字や線を描画しています。


final class SamplePage: PDFPage {
private let width = 1024
private let height = 768
private let title: String
private let contents: String

init(title: String, contents: String) {
self.title = title
self.contents = contents
super.init()
}

override func draw(with box: PDFDisplayBox, to context: CGContext) {
super.draw(with: box, to: context)
UIGraphicsPushContext(context)
context.translateBy(x: 0.0, y: CGFloat(height))
context.scaleBy(x: 1.0, y: -1.0)
let rect = CGRect(x: 25, y: 25, width: width, height: 100)
let attributes = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 50),
NSAttributedStringKey.foregroundColor: UIColor.black]
title.draw(in: rect, withAttributes: attributes)

let rect2 = CGRect(x: 25, y: 200, width: width, height: 600)
contents.draw(in: rect2, withAttributes: attributes)
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: width, y: 100))
path.lineWidth = 5.0
path.stroke()
UIGraphicsPopContext()
}

override func bounds(for box: PDFDisplayBox) -> CGRect {
return CGRect(x: 0, y: 0, width: width, height: height)
}
}

あとはPDFDocumetクラスのインスタンスにPDFPageをinsertしていけば良いです。

let pdf = PDFDocument()

let contents = """
・ここにコンテンツを入力します。
"""

let firstPage = SamplePage(title: "タイトル", contents:contents)
pdf.insert(firstPage, at: 0)

複数ページ作成する時は同様にinsertを複数回呼ぶとできます。

ここまででpdfの準備はできました。

最後にファイルに書き出します。

if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {

let path = url.appendingPathComponent("output.pdf")
print(path)
pdf.write(to: path)
}

出力されたpathにPDFが出力されます 🎉


最後に

PDFKitを利用することで、簡単にSwiftでPDF資料を作ることができました!

テーマに対応したり、他のレイアウトでも作れるようになると本格的にSwiftで資料作ることが出来るようになりますね。

最後にソースコードを載せておきます!


ソースコード

import UIKit

import PDFKit

final class SamplePage: PDFPage {
private let width = 1024
private let height = 768
private let title: String
private let contents: String

init(title: String, contents: String) {
self.title = title
self.contents = contents
super.init()
}

override func draw(with box: PDFDisplayBox, to context: CGContext) {
super.draw(with: box, to: context)
UIGraphicsPushContext(context)
context.translateBy(x: 0.0, y: CGFloat(height))
context.scaleBy(x: 1.0, y: -1.0)
let rect = CGRect(x: 25, y: 25, width: width, height: 100)
let attributes = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 50),
NSAttributedStringKey.foregroundColor: UIColor.black]
title.draw(in: rect, withAttributes: attributes)

let rect2 = CGRect(x: 25, y: 200, width: width, height: 600)
contents.draw(in: rect2, withAttributes: attributes)
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 100))
path.addLine(to: CGPoint(x: width, y: 100))
path.lineWidth = 5.0
path.stroke()
UIGraphicsPopContext()
}

override func bounds(for box: PDFDisplayBox) -> CGRect {
return CGRect(x: 0, y: 0, width: width, height: height)
}
}

let pdf = PDFDocument()
let contents = """
・PDFKitをimportする。
・PDFPageのdrawをoverrideする。
・PDFDocumentにPDFPageをinsertする。
・PDFDocumentをファイル書き出し。
"""

let firstPage = SamplePage(title: "【PDFKit】Swiftでプレゼン資料を作る", contents:contents)
pdf.insert(firstPage, at: 0)
if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let path = url.appendingPathComponent("output.pdf")
print(path)
pdf.write(to: path)
}