AdventCalendar
PDF
Swift

【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)
}