首页 > 解决方案 > Swift 中的错误处理:从一个枚举到另一个枚举的错误

问题描述

我在ServiceClient中有这段代码。它处理服务级调用,如signIn(user, password, completion), listObjects(completion),addObject(objectID, content, completion)getObject(id, completion)。它包含(但不子类化)一个APIClient,它只执行基本的 HTTPS 服务,如perform(request, completion).

我真的不希望位于此之上的控制器将 404 视为成功,这意味着在 ServiceClient 中捕获错误。所以这个想法是 APIClient 处理网络错误,而 ServiceClient 处理意外的 HTTP 结果。

所以我最终在 ServiceClient 中得到了这个,其中错误invalidURL从 APIClient 枚举转换为 ServiceClient 枚举:

apiClient.perform(request) {result in
    switch result {
    case .success(let data):
        guard data.statusCode == 200 else {
            completion(.failure(.badResponse))
            return
        }
        completion(.success(data))
    case .failure(let error):
        switch error {
        case .invalidURL:
            completion(.failure(.invalidURL))
        case .requestFailed:
            completion(.failure(.requestFailed))
        case .decodingFailure:
            completion(.failure(.decodingFailure))
        }
    }
}

我认为在这种情况下,我只会让 APIClient 处理无效的 HTTP 状态代码,但更通用的解决方案是什么?在某些时候,我会希望为不同的服务客户端提供不同的错误代码,此时这又会成为一个问题。

标签: swifterror-handling

解决方案


我建议IntServiceClientAPIClient使用类型枚举。据我了解,这是您的自定义枚举。

因此,假设您拥有ServiceClientError并且APIClientError可以使用以下方式实现它们:

enum ServiceClientError: Int {
    case invalidURL, requestFailed, decodingFailure
}
enum APIClientError: Int {
    case invalidURL, requestFailed, decodingFailure
}

您可以创建自定义转换方法:

extension ServiceClientError {
    static func create(from apiClientError: APIClientError) -> ServiceClientError {
        return ServiceClientError(rawValue: apiClientError.rawValue)
    }
}

想要的功能:

apiClient.perform(request) {result in
    switch result {
    case .success(let data):
        guard data.statusCode == 200 else {
            completion(.failure(.badResponse))
            return
        }
        completion(.success(data))
    case .failure(let error):
        guard let serviceClientError = ServiceClientError.create(from: error) else {
            /// Handle incorrect behavior
            fatalError("Wrong enumeration mapping")
            return
         }
         completion(.failure(serviceClientError))
    }
}

推荐阅读