如何将Alamofire 5中的AFError转换为通用Error?
问题:Alamofire实现NetworkService协议时的AFError转通用Error问题
我正尝试开发一款支持闭包、async和Combine特性的通用网络层,要求该网络层不依赖任何第三方库。协议定义如下:
import Combine import Foundation protocol NetworkService { // Closure func get<ResponseModel>(endpoint: String, response: ResponseModel.Type, completion: @escaping (Result<ResponseModel, Error>) -> Void) where ResponseModel: Decodable // Async func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) async -> Result<ResponseModel, Error> where ResponseModel: Decodable // Combine func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) -> AnyPublisher<Result<ResponseModel, Error>, Never> where ResponseModel: Decodable }
使用Alamofire实现该协议时出现类型转换错误,实现代码如下:
import Alamofire import Combine import Foundation final class AlamofireService: NetworkService { let session: Session // Encoder and Decoder let encoder = JSONEncoder() let decoder = JSONDecoder() init() { session = Session() } // Closure func get<ResponseModel>(endpoint: String, response: ResponseModel.Type, completion: @escaping (Result<ResponseModel, Error>) -> Void) where ResponseModel: Decodable { session .request(endpoint, method: .get) .validate() .responseDecodable(of: response, decoder: decoder) { completion($0.result) } } // Async func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) async -> Result<ResponseModel, Error> where ResponseModel: Decodable { let result = await session .request(endpoint, method: .get) .validate() .serializingDecodable(response, decoder: decoder) .result return result } // Combine func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) -> AnyPublisher<Result<ResponseModel, Error>, Never> where ResponseModel: Decodable { let result = session .request(endpoint, method: .get) .validate() .publishDecodable(type: response, decoder: decoder) .result() return result } }
错误信息:
- 闭包:无法将类型
Result<ResponseModel, AFError>转换为预期参数类型Result<ResponseModel, any Error> - Async:无法将返回表达式类型
Result<ResponseModel, AFError>转换为返回类型Result<ResponseModel, any Error> - Combine:无法将返回表达式类型
AnyPublisher<Result<ResponseModel, AFError>, Never>转换为返回类型AnyPublisher<Result<ResponseModel, any Error>, Never>
需要解决的是如何将AFError转换为通用Error类型以满足协议要求。
解决方案
核心思路是利用AFError本身遵循Error协议的特性,通过mapError或map操作完成类型兼容转换。
1. 闭包方法修复
修改闭包回调中的结果处理,通过mapError将AFError转为Error类型:
// Closure func get<ResponseModel>(endpoint: String, response: ResponseModel.Type, completion: @escaping (Result<ResponseModel, Error>) -> Void) where ResponseModel: Decodable { session .request(endpoint, method: .get) .validate() .responseDecodable(of: response, decoder: decoder) { responseData in let convertedResult = responseData.result.mapError { $0 as Error } completion(convertedResult) } }
2. Async方法修复
对异步获取的Result执行mapError转换错误类型:
// Async func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) async -> Result<ResponseModel, Error> where ResponseModel: Decodable { let result = await session .request(endpoint, method: .get) .validate() .serializingDecodable(response, decoder: decoder) .result return result.mapError { $0 as Error } }
3. Combine方法修复
在Combine流中通过map操作转换每个输出的Result错误类型,再进行类型擦除:
// Combine func get<ResponseModel>(endpoint: String, response: ResponseModel.Type) -> AnyPublisher<Result<ResponseModel, Error>, Never> where ResponseModel: Decodable { return session .request(endpoint, method: .get) .validate() .publishDecodable(type: response, decoder: decoder) .result() .map { $0.mapError { $0 as Error } } .eraseToAnyPublisher() }
内容的提问来源于stack exchange,提问作者wynioux
相关产品推荐
相关产品推荐

