Swiftを使ってみよう 第3回:PDFViewerをつくってみる

この記事は2014年8月1日に書かれたものです。内容が古い可能性がありますのでご注意ください。


SwiftでPDFViewerを作成

今回はSwiftを使用してちょっとしたものを作成してみましょう。
Objective-CでPDFViewerを作成する 第1回で作成したPDFViewerをSwiftで書いてみましょう。

◆プロジェクトの作成

プロジェクトの作成などは前回の記事やObjective-Cの記事と同じです。
Single View Applicationを選択し言語としてSwiftを選択します。リソースとしてPDFファイルを
追加しますが方法はObjective-C版と同じとなります。
アプリケーションの構成もObjective-Cの記事と合わせてViewControllerでCGPDFDocumentRefを作成し、
表示はUIViewを継承したクラスを作成してそちらで行うことにします。
ではクラスの作成から始めましょう。

◆クラスの作成

クラスを作成するために新しくswiftファイルを作成します。作成方法はプロジェクトフォルダのコンテキストメニューから
「NewFile」を選択します。そしてファイル名や保存場所を指定します。
スクリーンショット 2014-07-18 22.09.10

ここでObjective-Cと異なっているのが、Objective-Cの場合はどのクラスを継承するのかを選択しましたが
Swiftでは選択するところがありません。
とりあえずそのまま先に進みます。
出来上がったファイルを見てみましょう。今回は「PDFView」というクラスにしているので「PDFView.swift」となっています。コードの方ですが「import」文が1行あるだけです。
pdf-s-3-2

Swiftでのクラス定義は以下のように行います。

class クラス名:継承元クラス{
}

今回のコードの場合は次のようになります。

class PDFViewer:UIView{

}

Objective-Cより見やすくなっているのではないでしょうか。
では次に処理を実装していきましょう。

◆関数の作成

処理の流れ自体はObjective-Cのコードと同じようにしていきます。
PDFViewクラスの方ではdrawRect内にPDFドキュメントの描画処理を記述していきます。
そこでクラス内にdrawRect関数を作成します。

Swiftで関数を作成する場合は以下のように記述します。

func 関数名(仮引数名:仮引数の型・・・) -> 戻り値の型{

}

funcの後ろに関数名をつけます。引数がある場合は仮引数名を指定し「:」を挟んでその型を指定します。
戻り値の型は()の後ろに->をつけてそこに記述します。
ただ今回実装するdrawRectはスーパクラスで既に用意されている関数であるためオーバライドする必要があります。
Swiftの場合、前回に説明したようにオーバライドする関数にはoverrideを使用します。

override func 関数名・・・・・

drawRectの処理の中はObjective-C同様にCGContextDrawPDFPageを使用して記述していきます。
では次にコードを見てみましょう。

◆PDF表示用コードの確認

まずPDFを描画するためのクラスであるPDFView.swiftファイルです。

import Foundation
import UIKit
class PDFView: UIView{
    var _pdfPage: CGPDFPageRef?
    ovarride func drawRect(rect: CGRect){
        var context:CGContextRef = UIGraphicsGetCurrentContext();

        //上下を反転させる
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextTranslateCTM(context, 0, -CGRectGetHeight(rect));

        //PDFページのサイズを取得
        var pdfRect:CGRect = CGPDFPageGetBoxRect(_pdfPage, kCGPDFArtBox)
        CGContextScaleCTM(context,
                          rect.size.width/pdfRect.size.width,
                          rect.size.height/pdfRect.size.height)
        CGContextDrawPDFPage(context, _pdfPage)
    }

}

プロパティとして変数を宣言しているところ以外はあまり元のファイルと変わっていません。
変数の宣言時に型の後ろに「?」がついています。これはオプショナル型というものです。
これがどういったものか見てみましょう。

◆オプショナル型

オプショナル型は値が入っていない変数に使用されるものです。
ためしに以下のように変更してみてください。

var _pdfPage

この場合、「Type annotation missing in pattern」と出ます。型アノテーションが見つかりませんということになります。
Swiftは代入される値から型を推測してくれるため、例えば「var _pdfPage=”a”」とすれば勝手にstring型と判断されます。
しかし今回のように初期の値なしで宣言された場合は型がわかりません。それでエラーとなります。
では型をつければそれでいいかといえばそうでもありません。以下のように宣言してみてください。

var _pdfPage:CGPDFPageRef

今度は「class ‘PDFView’ has no initializers」とエラーが出ます。
これは初期化のためのinitializersがないということになります。Swiftでは通常の変数では値が入っている必要が
あります。そこでinitメソッドを実装し、_pdfPageに値を格納する必要が出てきます。

ただ宣言時には値が決まっていなくてデータが入っていない変数というものを使用したい場合があります。
何もないを表す「nil」を代入すればよいのですが、先ほども述べたように通常の変数は値が入っていなければならない
ので使えません。
そういったときにオプショナル型として宣言することで「nil」を代入できます。

◆ViewControllerのコード確認

次にViewControllerの方を見てみましょう。
こちらもObjective-Cの場合と同様PDFドキュメントを読み込む処理をしています。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        var url:NSURL = NSBundle.mainBundle().URLForResource("sample.pdf", withExtension:nil)
        var pdf:CGPDFDocumentRef = CGPDFDocumentCreateWithURL(url);
        var rect = UIScreen.mainScreen().bounds;
        var myview:PDFView = PDFView(frame:rect);
        myview._pdfPage = CGPDFDocumentGetPage(pdf, 1)
        self.view.addSubview(myview)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

リソースのパスを読み込むあたりの関数の呼び出しや変数の宣言以外使っているものは特に変わりません。
(当たり前といえば当たり前ですが)
関数の引数にはObjective-Cでセレクタとして指定していたものが入ります。
短いコードなのでそれほど劇的にコードが変わっているわけではありませんが、今後機能を増やしていくにつれて
いろいろ出てくるのかなと思います。

  • このエントリーをはてなブックマークに追加

PAGE TOP