【问题标题】:Switch behavior when new enum values are added添加新枚举值时的切换行为
【发布时间】:2023-03-19 17:54:01
【问题描述】:

注意:这不再相关。最新版本的 Swift 具有多种功能,可以通过各种方式解决枚举二进制兼容性问题,例如 @unknown default、冻结枚举等。

HealthKit 中的各种枚举往往会随着 iOS 的每个版本添加新的值。例如,HKWorkoutActivityType 自推出以来在每个 iOS 版本中都添加了新值。

假设我正在使用 Swift switch 语句将此枚举映射到字符串值:

extension HKWorkoutActivityType {
    var displayName: String {
        switch self {
            case .americanFootball: return "American Football"
            // ...Exhaustive switch statement, with a line for every enum case.
            // Including values added in iOS 10 and 11...
            case .taiChi: return "Tai Chi"
        }
    }
}

let event: HKWorkoutEvent = ...
print("Activity type is: \(event.type.displayName)")

此 switch 语句针对 iOS 11 SDK 编译,运行良好,并且向后兼容旧 iOS 版本。注意编译的时候switch语句是穷举的,所以没有default的情况。

但如果在 iOS 12 中添加了新的 HKWorkoutActivityType 值,并且我不重新编译这段代码,displayName getter 将如何处理新的枚举值?我应该期待崩溃吗?未定义的行为?它是否取决于枚举的类型(例如,这里是 Objective-C NS_ENUM,但 Swift 枚举的行为会有所不同)?等等

【问题讨论】:

  • 目前讨论较多,比较github.com/apple/swift-evolution/blob/master/proposals/…(以及其中的 swift-evolution 邮件列表的链接)。
  • @MartinR 感谢您提及该提案,我已经忘记了。该提案说“如果实际遇到未知的枚举情况,Swift 4 程序将在运行时捕获”——这可能是我问题的答案。
  • 请添加“未知默认”编辑作为此问题的实际答案!

标签: swift healthkit


【解决方案1】:

FWIW,这是this Swift Evolution proposal 正在解决的部分问题。 希望他们也能决定一个很好地满足此类问题的解决方案!

长话短说,您可以通过添加默认情况(即使编译器会对您大喊大叫)或使用版本标签来避免此问题。然而,这个问题目前可能属于“未定义”。

长篇大论:

当前版本的 Swift 不具备 ABI 稳定性,因此编译后的 Swift 应用程序不保证(几乎肯定不会)与使用较新版本编译的框架接口(平台的原因框架仍然是Objective-C)。

因此,此类更改如何影响 Swift 是一项正在进行的工作。当 Swift 5 发布时,我们可能会对如何处理此类问题有更好的定义。在那之前添加默认和/或版本检查可能是要走的路。

【讨论】:

    【解决方案2】:

    非常很有趣的问题,并且投了赞成票。我知道没有办法完美在 (a) Xcode 9 和 (b) iOS 11 中进行测试。但这可能是你的答案。

    如果if #available(iOS 12, *),我认为想要的 解决方案,但有问题。封装整个switch语句?只是添加了 iOS 12?

    结果应该是 Xcode 中的目标 iOS 版本和 Swift 编译器之间的结果,它被覆盖了 - 并且应该产生一个错误(希望能解释 iOS 11 是目标但只有一些东西可用的问题在 iOS 12 中)表示您需要使用 (a) if #available(iOS 12, *) 某处或更改您的目标。

    我知道没有简单的方法可以在不重建的情况下对其进行测试。这对你的问题是不可或缺的!因此我猜规则是:

    在新的 iOS(和相关的 Xcode)版本发布时始终重建您的应用程序。

    考虑到你的这一部分对你的代码拥有所有权。

    【讨论】:

    • 当然,及时更新应用程序当然是最好的解决方案。但即使您及时将更新的应用程序发布到 App Store,用户也可能不会立即更新应用程序 - 所以这里讨论的场景总是有可能的。
    • 我完全同意。在将其作为“答案”之前,我想。虽然不是一个真正的答案,(1)我真的不知道会是什么,(2)它比单纯的评论效果更好。事实是恕我直言,开发人员只能做这么多......取得所有权,测试,尽快使用测试版,保持更新......从那里开始,用户/消费者需要拥有所有权。如果你的应用程序因为没有做好你的工作而中止,那是你的责任。但是,如果那里有应用程序更新并且用户使用的是旧版本?就在他们身上……
    • 如果是您的框架/枚举(或来自第三方的某些东西,此时您确实可以选择不使用),那就是坏了......绝对,这不仅取决于您,而且我认真怀疑它会建立!如果是苹果?他们在这方面做得很好。 WWDC 引入了几个月内不会出现的这些东西(以及新版本的 Xcode)。而在那个新的/beta 版本的 Xcode(只能使用新的/beta OS 目标)中,您也无法构建。你问了一个很好的问题——理论上。 (因此,我投了赞成票。)
    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多