Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using @unknown default in swift 5 enum : How to suppress "Default will never be executed" warning?

Let's say I have an existing code as follows:

enum SomeEnumCases {
  case existing
  case alreadyExisting
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase {
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  }
}

Now, if I were to add a new case the the enum, the function above would show a compile error saying the switch case must be exhaustive, and I would be FORCED to handle the new missing case. I would add a third case in the switch statement, or add a default statement.

Now, I order to handle such unforeseen enum cases, I would like to add an @unknown default case to the existing function above. The only problem is, now it would give me a warning saying Default will never be executed.

So the question is, how do I future-proof my enum such that I can:

  1. Exhaustively handle all current enum cases, AND
  2. Have a default handling mechanism for the future unknown case, AND
  3. See a warning only when newer cases are added and these cases must be handled by the default case.

That means, the following code SHOULD NOT give warnings:

enum SomeEnumCases {
  case existing
  case alreadyExisting
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase {
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  @unknown default: // <-- warning: Default will never be executed: should be suppressed
    print("Alright, this is something new and exciting !!")
  }
}

but the following code SHOULD give a warning:

enum SomeEnumCases {
  case existing
  case alreadyExisting
  case new
}

func doSomething(withEnums enumCase: SomeEnumCases) {
  switch enumCase { // <-- warning: Switch must be exhaustive: This should stay.
  case .existing:
    print("This case was already existing")
  case .alreadyExisting:
    print("This case was already existing too...")
  @unknown default:
    print("Alright, this is something new and exciting !!")
  }
}

Is that possible through @unknown or otherwise ?

like image 720
Mehul Parmar Avatar asked Mar 30 '19 16:03

Mehul Parmar


People also ask

Should enums be capitalized Swift?

The name of an enum in Swift should follow the PascalCase naming convention in which the first letter of each word in a compound word is capitalized. The values declared in an enum — up , down , left and right — are referred to as enumeration case.

Can Swift enums have methods?

Swift's Enum can have methods. It can have instance methods and you can use it to return expression value for the UI. Let's look at the code above.

Can enum be extended Swift?

A Swift extension allows you to add functionality to a type, a class, a struct, an enum, or a protocol.

What is @frozen in Swift?

Introduced with Swift 5, the @unknown attribute is particularly useful when switching over a nonfrozen enumeration. While the @frozen attribute is used on familiar enums such as Result or Optional within the standard library.. ..


1 Answers

The warning is probably somewhat misleading as the spec says (emphasis added):

A nonfrozen enumeration is a special kind of enumeration that may gain new enumeration cases in the future—even after you compile and ship an app. Switching over a nonfrozen enumeration requires extra consideration. When a library’s authors mark an enumeration as nonfrozen, they reserve the right to add new enumeration cases, and any code that interacts with that enumeration must be able to handle those future cases without being recompiled. Only the standard library, Swift overlays for Apple frameworks, and C and Objective-C code can declare nonfrozen enumerations. Enumerations you declare in Swift can’t be nonfrozen.

So it's not so much that the branch will never be executed but that the feature is completely unsupported for your SomeEnumCases user-defined Swift enum.

There seems to be no supported way of doing what you wish in Swift 5, and some indications that adding cases is seen as a breaking change as it could/would break binary compatibility, but Swift is an ever moving target...

like image 62
CRD Avatar answered Oct 28 '22 04:10

CRD