はじめに
以下のような列挙型を定義することはよくあると思います。
enum SampleResult {
case success
case failure(LocalizedError)
}
これをEquatable
に準拠させようとすると以下のような関数を実装しなければいけません。
enum SampleResult: Equatable {
case success
case failure(LocalizedError)
static func == (lhs: SampleResult, rhs: SampleResult) -> Bool {
}
}
よくある解決策
localizedDescription
を比較しています。
しかし、別のエラーでもlocalizedDescription
は一緒にしていることがあると思います。
これでは正確な比較になりません。
enum SampleResult: Equatable {
case success
case failure(LocalizedError)
static func == (lhs: SampleResult, rhs: SampleResult) -> Bool {
switch (lhs, rhs) {
case (.success, .success):
true
case let (.failure(lhsError), .failure(rhsError)):
lhsError.localizedDescription == rhsError.localizedDescription
default:
false
}
}
}
解決策
enum SampleResult: Equatable {
case success
case failure(LocalizedError)
static func == (lhs: SampleResult, rhs: SampleResult) -> Bool {
switch (lhs, rhs) {
case (.success, .success):
true
case let (.failure(lhsError), .failure(rhsError)):
String(reflecting: lhsError) == String(reflecting: rhsError)
default:
false
}
}
}
解説
以下のような2つのエラーがあります。
import Foundation
enum DemoError1: LocalizedError {
case networkError
case serverError
}
enum DemoError2: LocalizedError {
case networkError
case serverError
}
String(reflecting:)
でエラーを出力すると、プロジェクト名.エラー列挙型名.エラー名
が文字列に変換されます。
import Foundation
print(String(reflecting: DemoError1.networkError))
print(String(reflecting: DemoError1.serverError))
print(String(reflecting: DemoError2.networkError))
print(String(reflecting: DemoError2.serverError))
// Demo.DemoError1.networkError
// Demo.DemoError1.serverError
// Demo.DemoError2.networkError
// Demo.DemoError2.serverError
以下のようなネストされた同名のエラーであってもパスが違うので別のものとして認識できます。
import Foundation
struct HomeView {
enum DemoError: LocalizedError {
case networkError
case serverError
}
}
struct SearchView {
enum DemoError: LocalizedError {
case networkError
case serverError
}
}
print(String(reflecting: HomeView.DemoError.networkError))
print(String(reflecting: HomeView.DemoError.serverError))
print(String(reflecting: SearchView.DemoError.networkError))
print(String(reflecting: SearchView.DemoError.serverError))
// Demo.HomeView.DemoError.networkError
// Demo.HomeView.DemoError.serverError
// Demo.SearchView.DemoError.networkError
// Demo.SearchView.DemoError.serverError
おわり
この実装で何か問題がありましたら、コメントで教えていただきたいです。