在swift 5枚举中使用@unknown默认值:如何抑制“将永远不会执行默认值”警告?

时间:2019-03-30 16:32:08

标签: swift enums warnings swift-playground swift5

比方说,我已有如下代码:

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...")
  }
}

现在,如果我要为枚举添加新的大小写,则上面的函数将显示一个编译错误,表明切换大小写必须是详尽无遗的,并且我将被迫处理新的丢失的大小写。我会在switch语句中添加第三种情况,或添加默认语句。

现在,我要处理这种无法预料的枚举案例,我想在上面的现有函数中添加一个@unknown default案例。唯一的问题是,现在它会给我一个警告,说Default will never be executed

问题是,我该如何对枚举进行将来的证明,以便我可以做到:

  1. 详尽处理当前所有枚举案例,并且
  2. 具有针对未来未知案例的默认处理机制,并且
  3. 仅当添加了新的案例并且这些案例必须由默认案例处理时,才显示警告。

这意味着,以下代码不应发出警告:

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 !!")
  }
}

,但以下代码应发出警告:

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 !!")
  }
}

可以通过@unknown还是其他方式实现?

1 个答案:

答案 0 :(得分:6)

正如spec所说(强调)那样,该警告可能会引起误解:

  

非冻结枚举是一种特殊的枚举,即使在编译和发布应用程序之后,它也可能在将来获得新的枚举用例。切换非冻结枚举需要额外考虑。当图书馆的作者将枚举标记为非冻结枚举时,他们保留添加新枚举案例的权利,并且与该枚举进行交互的任何代码必须都必须能够处理这些将来的案例而无需重新编译。只有标准库,Apple框架的Swift叠加层以及C和Objective-C代码才能声明非冻结枚举。 您在Swift中声明的枚举不能被冻结

因此,分支永远不会执行只是您的SomeEnumCases用户定义的Swift枚举完全不支持该功能。

在Swift 5中似乎没有受支持的方式来实现您的期望,并且有迹象表明,添加案例被视为一项重大更改,因为它可能/将破坏二进制兼容性,但是Swift是一个不断发展的目标...