【问题标题】:String to enum mapping in SwiftSwift 中的字符串到枚举映射
【发布时间】:2017-05-19 16:25:30
【问题描述】:

我在 Swift 中定义了一个枚举,如下所示:

 public enum Command:String {

   case first = "FirstCommand"
   case second = "SecondCommand"
   ...
   ...
   case last = "lastCommand"
 }

现在我从服务器收到一个命令字典,并从中提取命令字符串。命令字符串通常是 Command 枚举中的原始值之一,或者有时它可能是枚举之外的命令(例如,在客户端/服务器的未来版本中引入了新命令,但客户端仍然是旧的)。在这种情况下,在 Swift 3 中使用 switch 语句的方式是什么?如何将命令字符串类型转换为枚举并在 switch 默认情况下处理未知命令?

【问题讨论】:

    标签: swift enums


    【解决方案1】:

    我会尝试使用传入字符串的原始值创建Command,并且只有在成功时才使用switch。如果失败,则在另一个例程中处理未知命令。

    喜欢:

    guard let command = Command(rawValue: incomingString) else {
        handleUnknownCommand(incomingString)
        return
    }
    
    switch command {
        case first:
            ...
    }
    

    【讨论】:

    • 一个可能的变体是let command = Command(rawValue: incomingString) ?? .unknown,带有一个专用的case unknown
    • 可以,只要我们可以依赖服务器不发送映射到.unknown的字符串即可。知道哪些是合法命令,哪些是意外命令可能很有价值。
    • 您可以定义case unknown = "?",这样就不太可能发送确切的命令字符串:) – 但这只是一个建议,您的解决方案完全可以。
    • 你说服了我!
    • @JoshuaKaden:实际上,未知情况如何定义并不重要,见下文。
    【解决方案2】:

    Joshua's solution 的一个小变化是添加一个专用的 用于所有未知命令的枚举的大小写:

    public enum Command:String {
    
        case first = "FirstCommand"
        case second = "SecondCommand"
        // ...
        case last = "lastCommand"
        case unknown = "<unknownCommand>" 
    }
    

    现在你可以使用(失败的)初始化器Command(rawValue:) 与 nil-coalescing 运算符 ?? 一起映射传入的字符串 到一个枚举值,所有未知的命令都被映射 给.unknown

    let command = Command(rawValue: incomingString) ?? .unknown
    
    switch command {
    case .first:
        // Handle first command
    case .second:
        // Handle second command
    case .last:
        // Handle last command
    case .unknown:
        // Handle unknown command
    }
    

    case unknown 使用哪个原始字符串并不重要,所以你 也可以定义

    case unknown = "???"
    

    如果你喜欢。编译器验证字符串是否不同于 所有其他原始字符串。如果服务器碰巧发送了那个确切的 字符串,那么它将被映射到.unknown

    【讨论】:

      【解决方案3】:

      这取决于你如何使用它,但你可以这样做:

      func getCommand(for string: String) -> Command { 
          switch string {
              case Command.first.rawValue: return .first
              case Command.second.rawValue: return .second
              ...
              default: return .newCommand
           }
       }
      

      我认为不可能在返回时从服务器创建新命令,但您可以构建一个具有 command 属性的类,该属性采用 String 并在整个应用程序中以不同的方式工作。

      【讨论】:

      • 对于枚举,switch 中的默认值不是强制性的,因为枚举已经很详尽了
      • @Md.IbrahimHassan 在这种情况下,虽然开关是字符串,而不是枚举。
      • 我也在做同样的事情,但我不喜欢每次都写 Command.first.rawValue, Command.second.rawValue,...。不过,我确实不小心给了答案!
      【解决方案4】:

      作为一种替代结构,您可以使用可选的大小写值并在开关中添加一个nil 处理程序作为“默认”值:

      enum Command: String {
          case first = "a", second = "b", third = "c"
      }
      
      let command = Command(rawValue: "d")
      
      switch command {
      case .first?:
          print("first")
      case .second?:
          print("second")
      case .third?:
          print("third")
      case nil:
          print("not found")
      }
      // prints "not found"
      

      【讨论】:

        【解决方案5】:

        利用CaseIterable 协议进一步扩展解决此问题的不同方法。

        public enum Command:String, CaseIterable {
            case first = "FirstCommand"
            case second = "SecondCommand"
            case last = "lastCommand"
            case unknown = "UnknownCommand"
            
            static func getCase(string:String) -> Command {
                return self.allCases.first{"\($0.rawValue)" == string} ?? .unknown
            }
        }
        

        用法如下:

        let textCommand = "SecondCommand"
        let unknownCommand = "weirdCommand"
        
        // What is the case label of the "textCommand"
        print ("\(Command.getCase(string: textCommand))")
        
        // The case label for our "unknownCommand" is
        print ("\(Command.getCase(string: unknownCommand))")
        

        您将 null 合并运算符的用法改为 Command 枚举。 它看起来有点过度设计,它可能是。享受吧!

        【讨论】:

          猜你喜欢
          • 2012-01-06
          • 2021-11-09
          • 2019-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-06
          相关资源
          最近更新 更多