From Swift 5, new case attribute @unknown
is introduced.
What is the exact difference when @unknown
is being used and not being used? In which case we have to use @unknown
keyword?
From Swift 5, new case attribute @unknown
is introduced.
What is the exact difference when @unknown
is being used and not being used? In which case we have to use @unknown
keyword?
From SE-0192: Handling Future Enum Cases (emphasis mine):
default case
For example:
@unknown default case
From Reinder's blog post on "What's New In Swift 5.0":
more Ref: Hacking with Swift
In the case of only using
default
, it's used as when ourswitch
doesn't match any of the options. Let's see a first exhaustive case:This example is exhaustive and we won't get any error. But what if we need to add options in our
enum
?In this second example, we will get an error
Switch must be exhaustive
. To avoid this error, we might implement a default case:If the user chose, Option C, he will fall into the default case. But what happens when we add an Option D, E, etc. into the Enum? If we don't change the
switch
they will all fall intodefault
. This might not be a problem, depending on what you want to implement.Now, with the
@unknown
, we continue catching all the other options, but the difference here is that the compiler we issue a warningSwitch must be exhaustive
(not an error!) if all known elements of the enum haven't been matched (i.e. the switch wasn't exhaustive).If we add an option D, E, etc, we will just see a warning and then decide if we want to implement the other cases (for example, we want a custom message for option D and E) or if we will just leave the default message "you chose another option". Think of it as a friendly remainder instead of a big red error :)
Other examples: https://www.raywenderlich.com/55728-what-s-new-in-swift-5
The answers that imply that you will ever get a warning for your enums are wrong. This is about how Swift treats C (and Objective-C) enums in an external library/framework. A few Swift standard library enums are affected.
Okay, so let's consider an actual example. We write an exhaustive switch against a Cocoa enum:
At this point we get a warning. Why?
Well, our switch is exhaustive now, but it might not always be exhaustive. What if the framework adds cases later? Our compiled code won't change, and so it will crash (trap) when the new case arrives into the switch.
So we need a way to allow our code to keep working even if the framework changes. The compiler therefore is telling us: "Add a default case, even though the switch is exhaustive."
Now, of course it would be possible to add an ordinary default case:
The problem with that is if the framework does change, we'll never hear about it. So there's a better way,
@unknown default
:This means: "Hey, compiler, I don't expect there to be any more cases, but if I ever try to compile this project against the framework and you discover that there is another case, warn me so that I can add it explicitly to my switch."
So that's what's special about
@unknown
. If another case is added behind our backs, the compiler will give us another warning telling us about it, and we can fix our code to include it. In other words, you obey the warning now to get rid of the warning now in exchange for a possible useful warning in the future.Another nice thing about this syntax is that if we add an
@unknown default
to a switch that is not exhaustive now, the compiler will warn us about that.