【Swift】do-catchとthrows文の使い方!エラーハンドリングのやり方

この記事からわかること
- Swiftのエラー処理(エラーハンドリング)の実装方法
- NSErrorクラスとErrorプロトコルの違い
- do-catch文の使い方
- throwとthrowsの違い
- deferステートメントとは
index
[open]
\ アプリをリリースしました /
Swiftのエラーハンドリングの方法をまとめていきます。
Handling Cocoa Errors in Swift
Error Handling
エラーハンドリングとは?
そもそもエラーハンドリングとはプログラム実行中に発生したエラーを適切に対象する処理のことです。様々なプログラミング言語でも使用される事柄であり、エラー処理や例外処理とも呼ばれます。
もちろんSwiftでもエラーハンドリングが行えるようにさまざまなものが用意されています。ポイントになってくるのは以下の5つです。
- NSErrorクラス/Errorプロトコル
- throwステートメント/throwsキーワード
- do-catchステートメント
- tryキーワード
- deferステートメント
エラーの定義や発火、その後の処理方法などを上記のポイントを使い分けながら処理することができます。ちなみにステートメントは文とも呼ばれたりしています。
NSErrorクラス
Swiftでのエラー処理はErrorプロトコルとして定義されており、Objective-CのNSErrorクラスと互換性が保たれています。まずはNSErrorクラスを見てみます。
NSError
クラスはObjective-Cで使用されていたエラークラスでエラーに関する3つの情報を保持しています。
Errorプロトコル
Error
プロトコルはSwiftにおけるエラー情報管理するためのプロトコルです。定義するときはenum(列挙型)などに準拠させ発生しうるエラー内容を列挙しておきます。
おすすめ記事:【Swift】enum(列挙型)の使い方!値型enumと関連型enumとは
NSErrorクラスとは互換性があるので、キャスト(型変換)することが可能です。
throwステートメント:エラーを投げる
Swiftではthrow
ステートメントを使ってエラーを投げることができます。
throw
の後には発生させたいErrorオブジェクトを渡します。NSError
も投げることが可能です。
throwsキーワード:エラー発生
エラーを発生させる処理が組み込まれた関数やメソッド、イニシャライザにはエラーをスローできることを示すためにthrows
キーワードをつける必要があります。これによりエラーをスコープ外に伝播させることができるようです。
”Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function.”
訳:スロー関数のみがエラーを伝播できます。非スロー関数内でスローされたエラーは、関数内で処理する必要があります。
引用元
例えば以下は文字列形式で受け取った数字を数値に変換するメソッドです。変換が失敗した時と10以上の値を渡された時にエラーが発生するようになっています。
do-catchステートメント
エラーの発生はdo-catch
ステートメントを使って捕捉します。doステートメントとcatchステートメントの2つで構成されており、do内でエラーがthrowされる可能性のあるメソッドを呼び出し、catch内でそのエラーを参照することができるようになります。
catchブロックではerror
パラメータが宣言されているので補足したエラーオブジェクトがerror
に格納されます。カスタムエラーの場合はキャストすることで特定のエラータイプにアクセスすることが可能になります。
tryキーワード
do内でエラーをthrowするメソッドを呼び出すにはtry
キーワードをつけます。またtry?/try!
を使用することでエラーを無視する(do-catchを使わない)ことも可能です。
try
エラーを捕捉したい場合はdo-catch
とtry
を使用して以下のように記述することでエラー処理を行うことができます。
try?
try?
を使用する場合はエラーが発生しても無視でき、コンパイルエラーが発生することはありません。
try!
try!
を使用する場合はエラーの発生を無視できますが、エラーが実際に発生した場合ランタイムエラーが発生してしまいます。なのでtry!
はエラーが確実に発生せず、エラーの伝播が必要ない時などに使用します。
全体のサンプルコード
deferステートメント
エラーが発生すると一連の流れの処理が中断され、最後に必ず実行したい処理があっても呼び出されないまま終了してしまいます。これを解決するのがdefer
ステートメントです。
defer
ステートメントは通常の処理の最後、またはエラーが発生した直後に実行される処理を定義できるステートメントです。do-catch
内で記述し、処理が終了またはエラーの発生したタイミングまで実行を延期します。後続で行いたい処理をキューに溜めていくイメージですかね?
例えば上記の場合エラーが発生しなければ「処理2処理1」が表示されますが、エラーが発生した場合は「処理1エラー発生」で終了します。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。