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

Apple库中为何将结构体用作枚举?以RenewalState为例

为什么Apple的部分结构体用法像枚举?

你观察到的这种情况是Apple常用的API设计模式——用结构体模拟枚举行为,StoreKit的RenewalState就是典型例子。这种设计不是bug,而是为了解决原生Swift枚举的局限性,具体原因和优势如下:

核心原因:枚举的扩展性限制

Swift原生枚举的case是封闭不可扩展的——一旦定义完成,外部(包括Apple后续的框架更新)无法新增case。如果用枚举定义RenewalState,后续新增状态时,所有没写default分支的switch代码都会直接编译失败,这对开发者非常不友好。

而结构体的静态属性可以在后续版本中自由新增,开发者只要在switch里保留default分支,就能兼容新状态,不会出现编译错误。

实现方式(以RenewalState为例)

这类结构体通常会做以下设计:

  1. 内部封装私有原始值(比如String或Int),禁止外部随意创建实例;
  2. 对外暴露一系列静态属性,对应枚举的各个“case”;
  3. 实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:32:15