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

Swift搭配Apollo时使用协议与枚举统一自动生成同源模型的最优方案问询

解决方案

方案1:用协议扩展补全实现(最优解)

你之前的协议方案报错,本质是没有给Apollo自动生成的CurrentUser、MyUser显式声明遵守UserProtocol。Apollo生成代码时不会自动遵守你自定义的协议,只要手动加扩展即可,不需要修改自动生成的源文件:

// 定义统一属性协议
protocol UserProtocol {
  var id: String { get }
  // 其他需要统一的属性也在这里声明
}

// 给自动生成的类型加扩展,已有对应属性不需要额外实现
extension CurrentUser: UserProtocol {}
extension MyUser: UserProtocol {}
// 后续新增其他自动生成的User类型,仅需加一行扩展即可

之后你的User结构体就可以直接用原来的实现,没有任何重复代码:

struct User {
  var id: String
  // 其他属性

  init(_ data: UserProtocol) {
    self.id = data.id
    // 其他属性直接从data取即可
  }
}

如果不同自动生成类型的属性名不一致,只需要在对应扩展里做适配即可:

// 比如某自动生成类型的id字段叫userId
extension OtherUser: UserProtocol {
  var id: String { userId }
}

方案2:优化枚举方案消除重复代码

如果你坚持要用枚举的方案,只需要把属性提取的逻辑统一放到枚举的扩展里,不需要在init里重复写switch:

enum UserType {
  case currentUser(CurrentUser)
  case myUser(MyUser)
}

// 给枚举统一实现属性协议
extension UserType: UserProtocol {
  var id: String {
    switch self {
    case .currentUser(let user): return user.id
    case .myUser(let user): return user.id
    }
  }
  // 其他需要的属性只需要在这里写一次switch逻辑
}

// 之后User的init就非常简洁,没有重复代码
struct User {
  var id: String

  init(_ data: UserType) {
    self.id = data.id
    // 其他属性同样直接从data取即可
  }
}

后续新增其他User类型,只需要在枚举里加case,然后在枚举扩展的switch里补对应分支即可,所有用到的地方都不需要修改。

内容的提问来源于stack exchange,提问作者CaptainStiggz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:15:08