Apple库中为何将结构体用作枚举?以RenewalState为例
为什么Apple的部分结构体用法像枚举?
你观察到的这种情况是Apple常用的API设计模式——用结构体模拟枚举行为,StoreKit的RenewalState就是典型例子。这种设计不是bug,而是为了解决原生Swift枚举的局限性,具体原因和优势如下:
核心原因:枚举的扩展性限制
Swift原生枚举的case是封闭不可扩展的——一旦定义完成,外部(包括Apple后续的框架更新)无法新增case。如果用枚举定义RenewalState,后续新增状态时,所有没写default分支的switch代码都会直接编译失败,这对开发者非常不友好。
而结构体的静态属性可以在后续版本中自由新增,开发者只要在switch里保留default分支,就能兼容新状态,不会出现编译错误。
实现方式(以RenewalState为例)
这类结构体通常会做以下设计:
- 内部封装私有原始值(比如String或Int),禁止外部随意创建实例;
- 对外暴露一系列静态属性,对应枚举的各个“case”;
- 实现
Equatable协议,让实例可以用switch匹配。
简化后的代码大概是这样:
struct RenewalState: Equatable, Sendable { private let rawValue: String // 模拟枚举case的静态属性 static let active = RenewalState(rawValue: "active") static let expired = RenewalState(rawValue: "expired") static let inBillingRetryPeriod = RenewalState(rawValue: "in_billing_retry_period") // 私有初始化器,禁止外部创建自定义实例 private init(rawValue: String) { self.rawValue = rawValue } }
这样你就能像用枚举一样写switch逻辑:
let renewalState: RenewalState = ... switch renewalState { case .active: print("订阅处于活跃状态") case .expired: print("订阅已过期") default: // 兼容未来新增的状态 print("未知的续订状态") }
额外优势
除了兼容性,这种设计还有两个好处:
- 灵活的关联数据:如果未来某个状态需要携带额外信息,结构体可以直接添加存储属性,而枚举的关联值绑定到特定case,修改起来更受限;
- API一致性:在复杂场景下,这种模式能平衡枚举的直观用法和结构体的扩展性需求。
内容的提问来源于stack exchange,提问作者Hamster
相关产品推荐
相关产品推荐

