Swift服务类中如何将Error转换为自定义APICallError枚举?
如何将通用Error转换为自定义APICallError枚举
这是个很常见的需求——把通用Error类型转换成自定义的枚举,方便调用方更清晰地处理不同错误场景。下面我给你详细讲下实现思路和代码示例:
第一步:完善自定义错误枚举(可选但推荐)
首先,建议给你的APICallError添加一个unknown case,用来处理无法匹配的未知错误,这样能保留原始错误信息,避免丢失关键调试数据:
enum APICallError: Error { case insufficientCredentials case malformedResponse case forbidden case unknown(Error) // 包裹无法识别的原始错误 }
第二步:编写转换函数
在你的服务类里,添加一个私有转换函数,负责把任意Error实例映射到APICallError:
private func convertToAPICallError(_ error: Error) -> APICallError { // 1. 如果错误本身就是APICallError,直接返回 if let apiError = error as? APICallError { return apiError } // 2. 处理常见的系统错误,比如URLError if let urlError = error as? URLError { switch urlError.code { case .userAuthenticationRequired, .userCancelledAuthentication: return .insufficientCredentials case .badServerResponse, .cannotParseResponse: return .malformedResponse case .forbidden: return .forbidden default: return .unknown(error) } } // 3. 可以添加其他自定义错误类型的处理逻辑 // 比如如果你的后端返回了特定的业务错误码,也可以在这里解析映射 // 4. 所有无法匹配的错误都归入unknown return .unknown(error) }
第三步:在服务方法中应用转换
在你的makeCall方法里,无论哪里产生了Error,都用这个转换函数处理后再传给onError回调:
class APIService { typealias APIResponse = (Data) -> Void typealias APIError = (Error) -> Void func makeCall(onSuccess: @escaping APIResponse, onError: @escaping APIError) { // 模拟实际的后端调用(这里用URLSession示例) guard let url = URL(string: "https://your-api-endpoint.com") else { onError(APICallError.malformedResponse) return } URLSession.shared.dataTask(with: url) { [weak self] data, response, error in guard let self = self else { return } // 处理请求阶段的错误 if let error = error { let convertedError = self.convertToAPICallError(error) onError(convertedError) return } // 处理响应阶段的错误(比如HTTP状态码) guard let httpResponse = response as? HTTPURLResponse else { onError(APICallError.malformedResponse) return } switch httpResponse.statusCode { case 200...299: // 成功响应,传递数据 guard let data = data else { onError(APICallError.malformedResponse) return } onSuccess(data) case 401: onError(APICallError.insufficientCredentials) case 403: onError(APICallError.forbidden) default: // 其他状态码包装成unknown错误 let statusError = NSError(domain: "APIService", code: httpResponse.statusCode, userInfo: nil) onError(APICallError.unknown(statusError)) } }.resume() } // 上面的转换函数放在这里 private func convertToAPICallError(_ error: Error) -> APICallError { if let apiError = error as? APICallError { return apiError } if let urlError = error as? URLError { switch urlError.code { case .userAuthenticationRequired, .userCancelledAuthentication: return .insufficientCredentials case .badServerResponse, .cannotParseResponse: return .malformedResponse case .forbidden: return .forbidden default: return .unknown(error) } } return .unknown(error) } }
调用方如何处理错误
当调用方使用你的服务时,可以轻松地通过switch语句处理不同的错误场景:
let apiService = APIService() apiService.makeCall(onSuccess: { data in // 处理成功返回的数据 }) { error in guard let apiCallError = error as? APICallError else { print("无法识别的错误类型") return } switch apiCallError { case .insufficientCredentials: // 提示用户重新登录 print("请重新登录以继续") case .malformedResponse: // 提示服务器响应异常 print("服务器返回无效数据") case .forbidden: // 提示无权限 print("你没有访问该资源的权限") case .unknown(let originalError): // 处理未知错误,可打印原始信息用于调试 print("发生未知错误: \(originalError.localizedDescription)") } }
关键要点总结
- 优先匹配已知错误类型:先检查错误是否已经是
APICallError,再处理系统或其他自定义错误。 - 保留原始错误信息:用
unknown(Error)包裹无法识别的错误,方便调试和后续扩展。 - 覆盖全场景:不仅处理请求阶段的错误,还要处理响应阶段的HTTP状态码错误,确保所有错误都能被转换。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

