【问题标题】:How to return a Swift enum for handling error conditions如何返回 Swift 枚举来处理错误情况
【发布时间】:2015-04-17 15:07:09
【问题描述】:

我正在尝试在 Swift 中创建一个简单的错误处理结构。我想做的是返回一个包含“成功”代码或“错误”代码的类型。但是为了让它有点棘手,在错误的情况下,我还想得到一条消息和一个诊断字符串。

我想出了这个,它编译得很好,就返回成功/错误而言效果很好:

enum PasswordValidationResult {
    case Success
    case PasswordError(message: String, diagnostic: String)

    func isValid() -> Bool {
        switch self {
        case .Success:
            return true
        case .PasswordError:
            return false
        }
    }
}

我可以返回所需的值:

return PasswordValidationResult.PasswordError(message: "You can't do that", diagnostic: "XYZ")

当我尝试引用返回值时,问题就来了。

显然,我可以使用 isValid() 函数来测试成功条件,但我找不到任何引用消息和诊断字符串的语法。

例如,试试这个:

  myError = someFunction()

  if myError == PasswordValidationResult.Error {
    // None of this will compile, at all...
    println(myError.message)
  }

【问题讨论】:

    标签: swift syntax error-handling enums


    【解决方案1】:

    您可以使用switch 将关联的值提取为具有元素名称的元组:

    let myError = someFunction()
    
    switch myError {
    case .Success:
        println("success")
    case .PasswordError(let err):
        println("message: \(err.message)")
        println("diagnostic: \(err.diagnostic)")
    }
    

    【讨论】:

    • 还有一个很好的提示......不知道你可以像这样抓住整个元组。
    【解决方案2】:

    访问这些值的另一种更方便的方法是将计算属性添加到您的 enum 中,为每个关联值:

    enum PasswordValidationResult {
        // ...
    
        var errorMessage: String? {
            switch self {
            case let .PasswordError(message, _):
                return message
            default:
                return nil
            }
        }
    
        var errorDiagnostic: String? {
            switch self {
            case let .PasswordError(_, diagnostic):
                return diagnostic
            default:
                return nil
            }
        }
    }
    

    那些属性将是nil 表示成功,当结果是错误时,您可以轻松访问所需的值。

    【讨论】:

      【解决方案3】:

      您可以使用switch 提取枚举的关联值:

      switch someFunction() {
      case .Success:
          println("It worked!")
      case .PasswordError(let message, let diag):
          println(message)
      }
      

      除了switch 所做的其他好事之外,如果您的案例耗尽了所有可能性(如这里 - 枚举必须是两个值之一),您不需要默认值。如果你忘记和错过了一个,编译器会警告你。

      注意,你也可以匹配特定的值:

      switch someFunction() {
      case .Success:
          println("It worked!")
      case .PasswordError("Password invalid", _):
          println("Please try again")
      case let .PasswordError(message, diag):
          // more general error handling
      }
      

      【讨论】:

      • 因此,在声明中给出PasswordError 元组名称的部分是没有意义的。
      • @nhgrif 不确定你的意思
      • case PasswordError(message: String, diagnostic: String)
      • 哦,我明白了。好吧,有两个字符串,我猜它的目的是记录哪个是哪个。否则,您必须查看文档才能知道第一个是消息,第二个是诊断。
      • 是的,但你可能最好使用一些不同类型的元组......
      猜你喜欢
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多