【问题标题】:Swift 2 - try multi-catchSwift 2 - 尝试多抓
【发布时间】:2016-05-25 16:16:39
【问题描述】:

我四处搜索了一番,但没有找到任何东西——在这个网站上什至没有一个问题——所以现在我想知道 Swift 2 是否像 Java 那样支持多捕获块。

Java-示例:

try {
    someMethod(); // throws ExceptionOne, ExceptionTwo
} catch(ExceptionOne | ExceptionTwo e) {
    handleMyException();
} catch(Exception e2) {
    handleOtherExceptions();
}

在 Swift 中,我无法实现类似的解决方案。这个question 解释了一种处理ErrorType 枚举的不同错误的好方法,但是我的要求似乎不同,因为我的错误是使用来自HTTP 响应的消息初始化的。这是我的枚举:

enum HTTPError: ErrorType {
    case BAD_REQUEST(message: String)
    case UNAUTHORIZED(message: String)
    case NOT_FOUND
    case INTERNAL_SERVER_ERROR(message: String)
    case NOT_IMPLEMENTED(message: String)

    static func getErrorForStatusCode(statusCode: Int, message: String? = nil) -> HTTPError {
        switch statusCode {
        case 400:
            return HTTPError.BAD_REQUEST(message: message!)
        case 401:
            return HTTPError.UNAUTHORIZED(message: message!)
        case 404:
            return HTTPError.NOT_FOUND
        case 500:
            return HTTPError.INTERNAL_SERVER_ERROR(message: message!)
        case 501:
            return HTTPError.NOT_IMPLEMENTED(message: message!)
        default:
            return HTTPError.INTERNAL_SERVER_ERROR(message: message!)
        }
    }
}

当我想抛出那个枚举的错误时,我使用这样的代码:

func someMethod() throws {
    ...
    HTTPError.getErrorForStatusCode(400, message: "Field X missing") // Actual values coming from HTTP-response
    ...
}

现在,在调用方法中,我必须分别捕获枚举的每个错误,尽管我希望它们都做同样的事情(NOT_FOUND 除外,但这并不重要):

try {
    someMethod() // throws
} catch HTTPError.BAD_REQUEST(let message) {
    // display 'message' to user
} catch HTTPError.UNAUTHORIZED(let message) {
    // display 'message' to user
} catch HTTPError.INTERNAL_SERVER_ERROR(let message) {
    // display 'message' to user
}
...

Swift 2 真的不包含 multi-catch 吗?或者是否有其他解决方案可以帮助我解决我的问题?

编辑:似乎我想要的行为不是很清楚:我想以同样的方式处理 HTTPError 类型的错误(HTTPError.NOT_FOUND 除外),这就是我要求的原因多抓。

我仍然会实现一个通用的 catch-block 来覆盖所有我不知道的错误(例如超时、nil-access 等),但是那些带有后端消息的错误应该被特殊处理。

谢谢, 胖乎乎的

【问题讨论】:

    标签: swift2 try-catch multi-catch


    【解决方案1】:
    enum Error: ErrorType {
        case E1
        case E2
        case E3
    }
    
    func foo(e: Error) throws {
        throw e
    }
    
    do {
        try foo(Error.E2)
    } catch Error.E1 {
        print(Error.E1) // only Error.E1
    } catch {
        print("error: ", error) // all other errors
    }
    /*
    error:  E2
    */
    

    【讨论】:

    • 这并不是真正的多重捕获,第二个捕获将选择所有其他错误,而不仅仅是我要指定的错误。
    • 第二个捕获除 Error.E1 之外的所有错误。你写了“我希望他们都做同样的事情(除了 NOT_FOUND)”
    • 是的,我知道的那些。但该方法可能会引发我不知道的其他错误。
    • 你不知道吗?在这种情况下,您的代码将崩溃....所有抛出​​的错误必须在您的代码中的某个地方捕获
    • @user3441734 不,并非所有抛出的错误都必须被捕获——那些你不会捕获的错误将理所当然地使程序崩溃。如果程序无法从错误中恢复,则崩溃是适当的响应。
    【解决方案2】:

    Swift 2 确实支持多捕获

    来自文档

    你在 catch 之后写一个模式来指示该子句有哪些错误 可以处理。 如果 catch 子句没有模式,则该子句 匹配任何错误并将错误绑定到名为 error 的局部常量。

    所以获取error 常量并使用switch 语句。

    do {
      try someMethod() // throws
    } catch let error as HTTPError {
      switch error  {
      case .NOT_FOUND:
        print("not found")
      case let message: // handle all errors with a message
        print(message)
      }
    }
    

    或使用catch 模式

    do {
      try someMethod() // throws
    } catch HTTPError.NOT_FOUND {
        print("not found")
    } catch let message {
        print(message)
    }
    

    这也是详尽无遗的,因为所有其他案例都有消息。

    除此之外,您(开发人员)应该确切地知道枚举中的案例数量,以便您可以可靠地处理它们。

    编辑:

    另一种解决方案是在enum 中添加一个associatedValue 属性

      var associatedValue : String {
        switch self {
        case BAD_REQUEST(let value) : return value
        case UNAUTHORIZED(let value) : return value
        case INTERNAL_SERVER_ERROR(let value) : return value
        case NOT_IMPLEMENTED(let value) : return value
        default: return ""
        }
      }
    

    并使用此 switch 语句

    do {
      try someMethod() // throws
    } catch HTTPError.NOT_FOUND {
      print("not found")
    } catch let error as HTTPError {
      print(error.associatedValue)
    }
    

    【讨论】:

    • 文档部分仍然没有真正描述多捕获,因为没有模式的 catch 子句将捕获所有错误,而不仅仅是我想要指定的错误(我的理解是 'let error as HTTPError ' 已经是一种模式)。不过,您的答案中的 switch 语句看起来很有希望,我将尝试在使用错误中收到的消息时实现它。
    • 我已经实现了你的 switch-example 并且效果很好,我看到的唯一问题是'message'不是字符串消息,而是完整的枚举值,所以 print( message) 将导致类似 BAD_REQUEST("Field X missing") 的结果。你有什么建议可以解决这个问题吗?
    • 我看到并添加了一个建议
    • 您的编辑工作正常。我之前尝试过使用枚举中的属性,但无法让它与消息一起使用,虽然它很简单......非常感谢,我接受了你的回答:)
    【解决方案3】:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      相关资源
      最近更新 更多