現在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)
となるので、どちらの場合でも、処理が順序良く処理されるので、これで一安心です。
はじめこれに気が付かず、最初に出した例で処理を書いていたので、例外が発生した時におかしくなってようやく気付きました。。。