You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:40:33