Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

@unknown default usage with enums in Swift

@unknown default has been introduced in Swift 5 with SE-0192. It’s a new addition to the way we can work with Swift enums and helps us to prepare for future changes. After updating your project to Swift 5 you might end up with a new warning in Xcode 10.2:

Switch covers known cases, but ‘UNAuthorizationStatus’ may have additional unknown values, possibly added in future versions

A new warning tells you to implement the @unknown default case
A new warning tells you to implement the @unknown default case

Basically, Swift warns you to be prepared for future changes.

Why do we need @unknown default to prepare for the future?

It’s quite an interesting question! The reason is Apple’s established process for evolving APIs. Whenever Apple adds a new enum case, it’s a source-breaking change. Say, for example, Apple introduces a new UNAuthorizationStatus case in the future, your project will not compile if you would’ve handled each case individually.

Frozen vs non-frozen enums

The change comes with so-called frozen and non-frozen enums. It basically means that frozen enums will never get any new cases. When dealing with non-frozen enums the @unknown keyword ensures that clients handle any future cases. For now, it looks like Apple made a decision based on expectations and made some enums frozen and some not. You can find the full list here.

Stay updated with the latest in Swift

Join 20,010 Swift developers in our exclusive newsletter for the latest insights, tips, and updates. Don't miss out – join today!

You can always unsubscribe, no hard feelings.

Do I ever need the @unknown case with my own enums?

Quoting from the Swift Evolution proposal:

A key note: in this version of the proposal, nothing changes for user-defined Swift enums. This only affects C enums and enums in the standard library and overlays today. (This refers to libraries that Apple could hypothetically ship with its OSs, as it does with Foundation.framework and the Objective-C runtime.) The features described here may be used by third-party libraries in the future.

In other words, unless you defined your enums in C, you’ll not create warnings on implementation level when dealing with your own defined enums.

How to use @unknown default

In the following example, we’re switching between user notification authorization statuses. This would’ve worked fine in Swift 4.2, but now triggers a warning.

switch userNotificationsAuthorizationStatus {
case .notDetermined:
    requestPermission()
case .authorized, .denied, .provisional:
    // No need to request permission.
    print("Didn't request permission for User Notifications")
}

Therefore, we can use a combination of the fallthrough keyword together with the new @unknown keyword.

switch userNotificationsAuthorizationStatus {
case .notDetermined:
    requestPermission()
case .authorized, .denied, .provisional:
    fallthrough
@unknown default:
    // No need to request permission.
    print("Didn't request permission for User Notifications")
}

The difference between default and @unknown default

@unknown default basically works the same as the regular default and therefore, matches any value. The main difference is that the compiler will produce a warning if all known elements of the enum have not yet been matched. New enum cases remain source-compatible as a result of throwing a warning instead of an error.

You can see the differences in the following two images. In this code example, I didn’t cover the authorized enum case. Without @unknown, we’re not warned and just handling the case as a “catch all”. With @unknown, we’re warned that we didn’t handle the authorized case.

Missing a case with only using default
Missing a case with only using default
Using @unknown default which warns us about the missing case
Using @unknown default which warns us about the missing case

Conclusion

The main point to take here; update your code to Swift 5 and check your warnings whenever a new iOS version comes out. It might be that there’s a new enum case for you to take care of!

 
Antoine van der Lee

Written by

Antoine van der Lee

iOS Developer since 2010, former Staff iOS Engineer at WeTransfer and currently full-time Indie Developer & Founder at SwiftLee. Writing a new blog post every week related to Swift, iOS and Xcode. Regular speaker and workshop host.

Are you ready to

Turn your side projects into independence?

Learn my proven steps to transform your passion into profit.