Swift enums and the danger of the default case
Context
A lot of the time in Swift we will use enums to define bits of state within an app. The beauty of enums is that they represent a complete set of possible options. As such, when switching on an enum we can guarantee that every possible option is accounted for.
One issue I see occasionally is abusing the default
case. Consider the following example:
enum Style {
case small
case big
}
func size(for style: Style) -> CGFloat {
switch style {
case .small:
8
default:
16
}
}
On the surface this seems perfectly reasonable, but imagine a new developer is tasked with adding a third style - medium
. Unless that dev already knows about the size(for:)
function, the app will start behaving incorrectly… silently…
enum Style {
case small
case medium
case big
}
func size(for style: Style) -> CGFloat {
switch style {
case .small:
8
default: // Uh oh!
16
}
}
The solution to this particular example is simple. If we explicitly list all the enum cases, when medium
is added, the compiler will prompt let us know that the switch must be exhaustive
and that we’ve not handled medium
.
enum Style {
case small
case medium
case big
}
func size(for style: Style) -> CGFloat {
switch style {
case .small:
8
case .medium:
12
case .big:
16
}
}
Conclusion
Obviously the example presented is contrived but the concept is worth applying whenever you are about to use a default
case.
The power of enums is in their completeness, so don’t throw that away with a default
case unless you’re sure that’s what you want!
And as a rule of thumb:
Never lay traps for future devs