Menu
Coddy logo textTech

do、try、catch

CoddyのSwiftジャーニー「ロジックとフロー」セクションの一部 — レッスン 45/56。

エラーを処理するための完全な形式は、do/try/catchです:

enum DivError: Error { case byZero }

func divide(_ a: Int, _ b: Int) throws -> Int {
    if b == 0 { throw DivError.byZero }
    return a / b
}

do {
    let r = try divide(10, 2)
    print(r)                      // 5
} catch DivError.byZero {
    print("can't divide by zero")
} catch {
    print("unknown error")
}

try は、エラーをスローする可能性のある呼び出しの前に置きます。呼び出しがエラーをスローした場合、制御は対応する catch にジャンプします。そうでない場合、実行は do ブロックを通り抜けて継続されます。

複数の catch 節は上から下へと実行され、switch 文と同様に最初に一致したものが適用されます。最後にある引数のない catch はすべてを捕捉する(キャッチオール)もので、コンパイラを満足させる(エラーを防ぐ)ために、ほとんどの場合これが必要になります。

challenge icon

チャレンジ

簡単

3つのケース emptynotIntegernegative を持つ enum ParseError: Error を定義してください。

以下の動作を行うスロー関数 parsePositive(_ s: String) throws -> Int を定義してください:

  • 空白をトリミングした s が空の場合は .empty をスローする
  • sInt として解析できない場合は .notInteger をスローする
  • 解析された値が < 0 の場合は .negative をスローする
  • それ以外の場合は解析された値を返す

stdinから1行読み込み、do/catch ブロック内で parsePositive を呼び出します。以下を出力してください:

  • 成功時は got: <n>
  • 各ケースに応じて error: emptyerror: not integer、または error: negative

入力が 42 の場合、出力は got: 42 となります。空行の場合は error: empty となります。abc の場合は error: not integer となります。

チートシート

Swiftのエラーハンドリングは do/try/catch を使用します。Error プロトコルに準拠した enum でエラーを定義し、エラーを投げる関数には throws をマークし、throw を使用してエラーを発生させます。

enum DivError: Error { case byZero }

func divide(_ a: Int, _ b: Int) throws -> Int {
    if b == 0 { throw DivError.byZero }
    return a / b
}

do {
    let r = try divide(10, 2)
    print(r)                      // 5
} catch DivError.byZero {
    print("can't divide by zero")
} catch {
    print("unknown error")        // すべてをキャッチ
}
  • try は、エラーを投げるすべての呼び出しの前に置く必要があります。
  • catch 句は上から下にマッチングされ、最初に一致したものが実行されます。
  • 最後に置かれた引数なしの catch は、すべてのエラーをキャッチする役割を果たします。

自分で試してみよう

let line = readLine()!

// TODO: enum ParseError; func parsePositive(_:) throws -> Int;
// 3つの分岐とキャッチオールを持つ do/try/catch
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

ロジックとフローのすべてのレッスン