Note: this is no longer relevant. Recent versions of Swift have multiple features that address enum binary compatibility in various ways, such as @unknown default
, frozen enums, etc.
Various enums in HealthKit tend to get new values added with each release of iOS. For example, HKWorkoutActivityType
has had new values added in each iOS version since its introduction.
Say I am mapping this enum to a string value using a Swift switch
statement:
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)")
This switch statement, compiled against the iOS 11 SDK, works fine and is backward compatible with older iOS versions. Note that at the time of compilation, the switch statement is exhaustive, so there is no default
case.
But if new HKWorkoutActivityType values are added in iOS 12, and I don't recompile this code, how will the displayName
getter behave for new enum values? Should I expect a crash? Undefined behavior? Does it depend on the type of enum (for example, here it's an Objective-C NS_ENUM
, but will Swift enums behave differently)? etc.
FWIW, this is the partially what this Swift Evolution proposal is addressing. Hopefully they will decide on a solution that satisfies issues like this nicely too!
Long story short, you may be able to avoid this issue by adding a default case, (even though the compiler will yell at you), or using version tags. However this problem likely falls under "undefined" currently.
The long story:
The current version of Swift does not have ABI stability, so a compiled Swift application is not guaranteed to (and almost definitely wont) interface with a Framework compiled with a newer version (the reason the platform Frameworks are still Objective-C).
So how this category of changes affect Swift is a work in progress. We will probably have a better definition of how to deal with this type of issue when Swift 5 is released. until then adding default and/or version checking is probably the way to go.