Error Handling

Error Handling

執筆済 ソフトウェア開発Swift

失敗を型と構文で明示する。

swift
enum NetworkError: Error {
    case timeout
    case badStatus(Int)
}

func fetch() throws -> Data { ... }

do {
    let data = try fetch()
} catch NetworkError.timeout {
    ...
} catch {
    print(error)
}

設計の特徴#

特徴 効果
throws がシグネチャに出る 失敗しうることが呼び出し側で分かる
try を書かされる どの行が失敗しうるか目視できる
エラーは enum で表す 種類を網羅的に扱える
検査例外ではない どんな型を投げるかは宣言しない(※)

※ Swift 6 では throws(MyError) という型付きスローが導入された。

try の変種#

swift
let a = try fetch()      // エラーを伝播する
let b = try? fetch()     // 失敗したら nil(Optional になる)
let c = try! fetch()     // 失敗したらクラッシュ

try?エラーの情報を捨てるので、 原因が分からなくなる。使いどころは限られる。

Result 型#

swift
enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
}

値として持ち回れるので、 非同期の完了ハンドラで使われてきた。 async/await の普及後は try await で書けるため、出番は減っている。

回復可能かどうかで分ける#

種類 手段
回復できる(通信失敗、入力誤り) throws
回復できない(前提条件違反) fatalErrorprecondition
プログラムの誤り assert(デバッグ時のみ)

回復できない状況で握りつぶすと、 壊れた状態のまま進んでしまう。 早く落とす方が安全なことがある。

参考文献#

ノート一覧を閉じる