現在PDFGeneratorの新規機能の追加だったり、より安全にPDFが出力できるように整えているのですが、
その中で、どうしても 例外 をdo〜try〜catchで処理しなくてはならなくて。
そんな時に、例えばPDFの描画を開始し、例外を返すかもしれないprocess()を実行するという流れがあった場合に、
do {
UIGraphicsBeginPDFContextToFile(outputPath, CGRectZero, nil)
try process()
UIGraphicsEndPDFContext()
} catch (let error) {
print(error)
}
処理が成功する場合は、UIGraphicsEndPDFContext()が呼ばれるのですが、tryで例外がキャッチされた場合は、UIGraphicsEndPDFContext()がスキップされてしまいます。危ない…
そうならないために、以下のアプローチをとります。
UIGraphicsBeginPDFContextToFile(outputPath, CGRectZero, nil)
do {
try process()
} catch (let error) {
print(error)
}
UIGraphicsEndPDFContext()
うーん、これでも間違ってはいないのですが、ちょっとスコープが広すぎる気がします。
そこで、deferを使って、doステートメントの中で収まるようにします。
deferは、そのスコープを抜けるときに中に書いた処理を実行してくれるものです。
今回のケースにはもってこいですね。
do {
UIGraphicsBeginPDFContextToFile(outputPath, CGRectZero, nil)
defer {
UIGraphicsEndPDFContext()
}
try process()
} catch (let error) {
print(error)
}
なんとなく、終了の処理を、process()より先に書くのは抵抗がありますが、
これで、tryで仮に例外がキャッチされて、catchステートメントに移行したとしても、UIGraphicsEndPDFContext()が呼ばれます。
流れとしては、
-
正常に処理される場合
- UIGraphicsBeginPDFContextToFile(outputPath, CGRectZero, nil)
- process()
- UIGraphicsEndPDFContext()
-
例外がキャッチされる場合
- UIGraphicsBeginPDFContextToFile(outputPath, CGRectZero, nil)
- process()
- UIGraphicsEndPDFContext()
- print(error)
となるので、どちらの場合でも、処理が順序良く処理されるので、これで一安心です。
はじめこれに気が付かず、最初に出した例で処理を書いていたので、例外が発生した時におかしくなってようやく気付きました。。。