0
1

【Swift】LocalizedErrorを持つ列挙型を比較したい

Posted at

はじめに

以下のような列挙型を定義することはよくあると思います。

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

おわり

この実装で何か問題がありましたら、コメントで教えていただきたいです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1