try、do、catchについて、ちゃんと調べてみた。
C++、C#、Javaなんかであるtry〜catchみたいなものだ。
まず、独自のエラーを列挙で定義する。
enum MyError:ErrorType {
case Hoge1
case Hoge2(Int)
}
エラー(例外?)を投げるところをdo囲って、受けるところをcatchで書く。
do {
// throw MyError.Hoge1
throw MyError.Hoge2(4)
} catch MyError.Hoge1 {
print("1.Catched Hoge1")
} catch MyError.Hoge2(let val) {
print("1.Catched Hoge2(\(val))")
}
MyError.Hoge2みたいにすると、何らかの値を渡すこともできる。
エラーを投げる関数を書いてみる。
// エラーを投げる関数定義
// 戻り値の型の前にthrowsを書いておく
func ThrowFunc() throws -> Int {
throw MyError.Hoge1
// return 1
}
戻り値の型の前にtrowsを書いとく必要がある。
エラーを投げる可能性のある関数(throwsが付いているやつ)を呼び出すときは、doで囲って関数名の前にtryを付ける。
do {
let r = try ThrowFunc()
} catch let err {
print(err)
}
do〜catchしない場合は、tryのあとに?を付けるか、!を付ける。
細かい説明は、次のソースコードの中に書いといたので省く。
//let r = try ThrowFunc() // do~catchしてないとコンパイルエラーになる
let r = try? ThrowFunc() // tryの後に?を付けるとコンパイルエラーにならない。
print(r) // rはInt?で、ここではnilになっている。(例外が投げられたらnilが代入されると言うことだ)
let r2 = try! ThrowFunc() // tryの後に!を付けるとコンパイルエラーにならない。
// けどr2はInt型なので、この例の場合実行時にエラーになる。
// 当たり前だが、エラーが起こらないのが明白な場合のみ使うべきだな。
print(r2)
次にJavaのfinallyにあたる部分はこんな感じだ。
doの括弧内にdeferで後処理を書く。deferはエラーを投げる関数より前に書いておかないといけない。
do {
defer {
print("1.後処理")
}
let r = try ThrowFunc()
// ↓ここだとThrowFuncでエラーになったとき、後処理が実行されない。
// けど、エラーじゃないときは、2.後処理、1.後処理の順で実行される。
// defer {
// print("2.後処理")
// }
} catch MyError.Hoge1 {
print("2.Catched Hoge1")
} catch {
print("2.Hoge1以外をキャッチ")
}
deferは、doと組み合わせないといけないわけではなく、スコープを抜けるときに実行されるので次ようなコードもOKだ。
func DeferTest()->Void {
print("defer test 1")
defer {
print("後処理?")
}
print("defer test 2")
}
DeferTest()
実行結果は、
defer test 1 defer test 2 後処理?
と表示される。