【Swift】開発中、とりあえず適当なエラーを投げたい…!ときのアイディア4選
この記事は SwiftWednesday Advent Calendar 2023 の11日目の記事です。
Swift でエラーを扱うには、Error
に準拠したカスタムタイプを用意する必要があります。
func someFunc() throws {
// あとでちゃんと書くから、
// 今はとりあえず適当なエラーを投げたい…!
}
「ちょっと今はエラーのタイプを用意しないで、適当に書きたい…!」「自分しか扱わない使い捨てのコードスニペットだから、エラーは適当に書いておいても大丈夫……!」と思ったとき、どのような表現ができるかまとめました。
自分以外の人が見るようなコード・プロダクトでは使わないことをおすすめします。
LocalizedError
に String
を準拠させる
【おすすめ】私は基本的にこの方法を使っています。Error
に準拠している LocalizedError
を String
が準拠するよう、以下のコードをどこかに書いておきます。
import Foundation
#if !(RELEASE) // 意図せずリリースビルドで使用されることがないようにする
extension String: LocalizedError {
public var errorDescription: String? { self }
}
#endif
すると、エラーを投げるべき場所において String
を使えるようになります。
func someFunc() throws {
guard /* ... */ else {
throw "エラーだよ"
}
// ...
}
LocalizedError.errorDescription
で self
を返すようにしたので、Error.localizedDescription
でその文字列を簡単に得ることができます。
do {
try someFunc()
} catch {
print(error) // エラーだよ
print(error.localizedDescription) // エラーだよ
}
Error
に String
を準拠させる
【おすすめ】Error
を String
が準拠するよう、以下のコードをどこかに書いておきます。
import Foundation
#if !(RELEASE) // 意図せずリリースビルドで使用されることがないようにする
extension String: Error {}
#endif
すると、エラーを投げるべき場所において String
を使えるようになります。
func someFunc() throws {
guard /* ... */ else {
throw "エラーだよ"
}
// ...
}
エラーを print(_:separator:terminator:)
などすると、その文字列を出力として得られます。
do {
try someFunc()
} catch {
print(error) // エラーだよ
print(error.localizedDescription) // The operation couldn’t be completed. (Swift.String error 1.)
}
Error
に準拠したタイプを投げる
【要注意】Swift に入っている Swift には元々 Error
に準拠したタイプがいくつか存在するため、それを借りるアイディアです。
import Foundation
func someFunc() throws {
guard /* ... */ else {
throw CancellationError()
}
// ...
}
例えば CancellationError
を投げてみました。
do {
try someFunc()
} catch {
print(error) // CancellationError()
print(error.localizedDescription) // The operation couldn’t be completed. (Swift.CancellationError error 1.)
}
しかしこの方法は、本来投げられるべき場面が決まっているエラーたちを、自分で用意する必要がないからといって勝手に借りて使用するため、使いどころには要注意です。
【もう一工夫】そのままリリースビルドしたときに、コンパイルエラーメッセージをわかりやすくする
たとえば、先述の CancellationError
を投げる例の場合、このままだとリリースビルドにおいてコンパイルエラーにならないため、CancellationError
が使われていることを失念する可能性があります。
そのようなときは、error(_:)
マクロを併せて記述しておくことで、ビルド設定がリリースに変わったときはコンパイル時エラーにする…… といったことが可能です。
#if DEBUG
throw CancellationError()
#else
#error("Implement me!")
#endif
NSError
を投げる
【ObjC のちから】Objective-C 時代からの資産である NSError
を投げるのも1つの方法です。
import Foundation
func someFunc() throws {
guard /* ... */ false else {
throw NSError(domain: "jp.tret.playground", code: 1)
}
// ...
}
do {
try someFunc()
} catch {
print(error) // Error Domain=jp.tret.playground Code=1 "(null)"
print(error.localizedDescription) // The operation couldn’t be completed. (jp.tret.playground error 1.)
}
もし、この NSError
のようにドメイン、エラーコードなどの情報を返すカスタムタイプを Swift で実装する場合は、CustomNSError
に準拠したカスタムタイプを実装することをおすすめします。
本来ならば……
本来であれば、Error
に準拠したカスタムタイプを用意し、適したエラーを投げることが必要です。エラーのためのカスタムタイプの作り方は Apple および Swift のドキュメントも参照してください。
- Error | Apple Developer Documentation https://developer.apple.com/documentation/swift/error
- Error Handling | Documentation https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling
Discussion