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
相关产品推荐
相关产品推荐

