Errorプロトコルの使い方
2021年03月09日
SwiftでAPIにアクセスした時や何か処理に失敗した時に Errorプロトコル に準拠したenumやstructをよく用います
Errorに準拠した型の定義方法
例えば以下のように定義をします
enum AppError: Error {
case network
case api(Int) //数値を渡す
case auth
case unkown(String) //文字列を渡す
}
エラーの投げ方
メソッドには引数の後に throws
キーワードをつけ、実際にエラーを投げる際には throw
文で投げます
func throwErrorSample() throws -> Void {
let hasNetworkError = false
let hasUnownError = true
if hasNetworkError {
throw AppError.network
}
if hasUnownError {
throw AppError.unkown("不明のエラー")
}
}
tryの使い方
エラーを持つメソッドに対して try
を用いる事が出来ます。
try
・ try!
・ try?
の3つの書き方 があります。
do-catchとtry
他言語のtry-catchと近い書き方が出来ます
do {
try throwErrorSample()
} catch APIError.network {
// .network のエラー場合
} catch APIError.unknown(let message) {
// .unknown のエラー場合
print(message)
// => "不明のエラー"
} catch {
// それ以外のエラー場合
}
try? と try!
do-catchを用いないSwiftらしい書き方が出来ます
参考に引数で渡したBool値を元にErrorを返すメソッドを使ってみます
struct User {
let uid: String
let name: String
}
/// 引数の値がtrueだった場合強制的に AppError.api を返す
func loadUserInfo(hasApiError: Bool) throws -> User {
if hasApiError {
throw AppError.api(404)
}
let user = User(uid: "uid-sample", name: "taro")
return user
}
try?
Errorがない場合はOptionalの値を、Errorの場合はnilを返します。
そのため guard
や if let
と相性良く使うことが出来ます。
// Errorが返らない場合
let user = try? loadUserInfo(hasApiError: false)
print(user)
// => Optional(User(uid: "uid-sample", name: "taro"))
/* guardと合わせて使う */
guard let user = try? loadUserInfo(hasApiError: false) else { return }
print(user)
// => User(uid: "uid-sample", name: "taro")
// Errorが返る場合
let user = try? loadUserInfo(hasApiError: true)
print(user)
// => nil
try!
Errorがない場合は値を返し、Errorの場合はクラッシュします。
// Errorが返らない場合
let user = try! loadUserInfo(hasApiError: false)
print(user)
// => User(uid: "uid-sample", name: "taro")
// Errorが返る場合
let user = try! loadUserInfo(hasApiError: true)
// => Fatal error: 'try!' expression unexpectedly raised an error: SwiftErrorSample.AppError.api(404)