Swift2.0からエラーハンドリングが追加され、try
を使えるようになりました。
また、Xcode7 beta6(あたり?)から、try
、try!
に加えtry?
が追加されました。
これにより、柔軟にtry
を使えるようになります。
まず、通常のtry
ですが、
do {
let object = try doSomething()
} catch (let error) {
print(error)
}
のように使います。必ずdo{ } catch {}
で用いて、try
はdo文内に書く必要があります。
次にtry!
ですが、上記のdo{ } catch {}
を使わず、 例外がキャッチされない のを条件にして書くことができます。
let object = try! doSomething()
ただ、もしdoSomething()
が例外を発生させた場合は強制終了します。
必ず例外が起こらない状況で、do{ } catch {}
でネストさせたくない場合はこれを用います。
そして、try?
の出番です。
これは、 例外が発生しなければその関数の戻り値を返し、 例外が発生すればnil を返すといったものになります。
勘違いしやすいのですが、try?
を指定して例外が発生した場合はエラーが変数に入るのではなく、 nil が返ってきます
func doSomething() throws -> String {
return "done!"
}
let object = try? doSomething()
// objectはString?型
こちらもtry!
と同様、do{ } catch {}
を使わずに済むので、
do{ } catch {}
を使う必要がなく、例外のエラーが何であるか必要なく、処理が成功するかしないかが必要な場合は、
このtry?
を使うとより簡潔に書けます。
- 例1: 値のチェック
func doSomething() throws -> String {
return "done!"
}
if let str = try? doSomething() {
print(str)
}
guard let str = try? doSomething() else {
return
}
print(str)
if let
文もしくはguard let
文で例外が起きなかった場合の値をキャッチできます。
- 例2: 例外が起こりうるかもしれないが、エラーを必要としない場合
_ = try? NSFileManager.defaultManager().removeItemAtPath("path")
このように、removeItemAtPath
の結果が成功であっても、例外発生であっても、特に例外の処理をしない場合は、do{ } catch {}
を書くよりは
簡潔に済ませられます。
ただ、removeItemAtPath
のように、関数の返り値がVoid
であっても、try?
を使う場合は、Void
またはnilが返るようになるので、
_ =
のようにして、使わない値を捨てる必要があります。
このtry
が出現する前から、Either型
、Result
と称されるものが出てきていて、エラーハンドリングをそれに委ねられることが多く、
スルーされがちなtry
さんですが、使いこなせると表現の幅が広がるので、是非try
を、できればtry?
さんも使ってあげてください。