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

Swift中如何创建兼容不同Endpoint类型的EndpointMapping数组?

解决泛型EndpointMapping无法存入同一数组的问题

核心原因

EndpointMapping<T>是泛型结构体,不同Endpoint实现对应不同的T,因此生成的EndpointMapping实例属于不同具体类型。Swift数组要求元素类型统一,直接声明[EndpointMapping]会触发编译错误。解决关键是通过类型擦除,用统一的非泛型协议包装异构泛型实例。

具体实现方案

1. 定义非泛型的统一接口协议

创建不包含关联类型的协议,封装请求并更新模型的核心行为:

protocol AnyEndpointMapping {
    func fetchAndUpdate(model: DashboardResponseModel, group: DispatchGroup)
}

2. 让泛型EndpointMapping遵循该协议

修改原EndpointMapping<T>实现上述协议,把请求、解析、赋值逻辑封装到协议方法内:

struct EndpointMapping<T: Endpoint>: AnyEndpointMapping {
    let endpoint: T
    let keyPath: WritableKeyPath<DashboardResponseModel, T.ModelType?>
    
    func fetchAndUpdate(model: DashboardResponseModel, group: DispatchGroup) {
        group.enter()
        // 替换为你实际的网络请求方法
        performRequest(with: endpoint) { result in
            defer { group.leave() }
            switch result {
            case .success(let parsedModel):
                model[keyPath: keyPath] = parsedModel
            case .failure(let error):
                // 根据需求处理错误,如日志上报
                print("请求\(endpoint.path)失败: \(error.localizedDescription)")
            }
        }
    }
    
    // 示例网络请求方法,需替换为项目实际实现
    private func performRequest(with endpoint: T, completion: @escaping (Result<T.ModelType, Error>) -> Void) {
        // 这里实现网络请求、JSON解码逻辑
        // 比如用URLSession发送请求,解码为T.ModelType
    }
}

3. 使用统一类型数组管理所有映射

现在可以声明[AnyEndpointMapping]类型的数组,自由添加不同端点的映射实例:

func loadDashboardData(completion: @escaping (DashboardResponseModel) -> Void) {
    let dashboardModel = DashboardResponseModel()
    let dispatchGroup = DispatchGroup()
    
    let endpointMappings: [AnyEndpointMapping] = [
        EndpointMapping(endpoint: CurrenciesEndpoint(), keyPath: \.currency),
        EndpointMapping(endpoint: UserEndpoint(), keyPath: \.user),
        EndpointMapping(endpoint: BalanceEndpoint(), keyPath: \.balance)
    ]
    
    endpointMappings.forEach { mapping in
        mapping.fetchAndUpdate(model: dashboardModel, group: dispatchGroup)
    }
    
    dispatchGroup.notify(queue: .main) {
        completion(dashboardModel)
    }
}

额外说明

  • 类型擦除的本质是把泛型特有的类型信息(如T.ModelType的解码、keyPath的类型)隐藏在结构体内部,对外仅暴露统一的行为接口。
  • 如果需要扩展功能(如自定义超时、请求优先级),可以在AnyEndpointMapping协议中添加对应方法,或在EndpointMapping中增加属性支持。

内容的提问来源于stack exchange,提问作者Burak Akyalçın

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 08:13:20