ProgrammingiOS開発者

Swiftにおけるエラーハンドリング(Error Handling)の仕組みを説明してください。どのようなエラータイプがあり、どのように処理しますか?throw/catchを使うべき時とResultを使うべき時はいつですか?

Hintsage AIアシスタントで面接を突破

回答。

Swiftは、Errorプロトコルとthrowtrycatchの構文を通じて厳格なエラーハンドリングシステムをサポートしています。独自のエラータイプを定義することができ、Errorから継承できます:

enum NetworkError: Error { case noInternet case serverError(code: Int) case unknown }

エラーをスローする可能性のある関数はthrowsとして宣言されます:

func fetchData() throws -> Data { // ... throw NetworkError.noInternet }

エラーはdo-catchブロックを使って処理できます:

do { let data = try fetchData() // データを操作 } catch NetworkError.noInternet { print("インターネットがありません") } catch { print("別のエラー: \(error)") }

もう一つのアプローチは、Result<T, Error>タイプを使うことで、try-catchなしで結果またはエラーを返すことができます:

func fetchData() -> Result<Data, NetworkError> { // ... return .failure(.noInternet) } let result = fetchData() switch result { case .success(let data): // OK case .failure(let err): // エラー処理 }

いつ使うべきか:

  • エラーが重要で無視できない場合はtry/catchを使用してください。
  • 関数が非同期の場合、または例外を使用せずにエラーを外部に渡したい場合はResultを使用してください。

トリック質問。

質問: 「文字列や数値など、任意のタイプのエラーを投げたり捕まえたりできますか?」

答え: いいえ、SwiftではErrorプロトコルに準拠したタイプのみをスローできます。

// 間違い: throw "StringError" // コンパイラはこれを許可しません // 正しい: struct MyError: Error {} throw MyError()

トピックに関する実際のエラーの例。


ストーリー

REST APIクライアントのプロジェクトで、エラーを文字列でスローしていました(throw "No data")。JavaScriptではコンパイルされましたが、Swiftに翻訳した際に致命的なコンパイルエラーが発生しました。


ストーリー

開発者はオプショナル値を介してエラーを返していました(エラー時にreturn nil)、throw/Resultを通じてではありませんでした。その結果、エラーに関する詳細が失われ、正しく処理することが難しくなり、Silent failsが発生しました。


ストーリー

分析の結果、アプリケーションのいくつかの部分で同じエラーが一つのErrorタイプにグループ化されていないことが判明しました。その結果、アプリケーションが同じ種類の失敗を異なる方法で処理し、UIが同じエラーに対して異なるメッセージを表示していました—保守とテストが困難でした。