我在 ServiceClient 中有此代码。它处理服务级调用,例如signIn(user, password, completion)
,listObjects(completion)
,addObject(objectID, content, completion)
,getObject(id, completion)
等。它包含(但不子类化) APIClient ,仅执行诸如perform(request, completion)
之类的基本HTTPS服务。
我真的不希望位于此之上的控制器成功处理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状态代码,但是对此,更通用的解决方案是什么?在某些时候,我需要为不同的服务客户端使用不同的错误代码,这时再次成为问题。
答案 0 :(得分:2)
我建议对 ServiceClient 和 APIClient 使用Int
类型枚举。
据我了解,这是您的自定义枚举。
因此,假设您拥有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))
}
}