将错误绑定到变量的Swift Catch Pattern

时间:2019-01-02 17:17:46

标签: xcode10 swift4.2 catch-block

使用Swift 4.2和XCode 10

在Swift 4.2中,DecodingError是一个枚举。 (当前)有四种不同的情况。我可以分别捕获每种情况,并绑定可用于记录错误的变量,如以下代码所示……

do {
    let model = try jsonDecoder.decode(BattleShip.self, from: jsonData!)
    print(model)
} catch DecodingError.dataCorrupted(let context) {
    print(context.debugDescription)
} catch DecodingError.keyNotFound(let key, let context) {
    print("\(key.stringValue) was not found, \(context.debugDescription)")
} catch DecodingError.typeMismatch(let type, let context) {
    print("\(type) was expected, \(context.debugDescription)")
} catch DecodingError.valueNotFound(let type, let context) {
    print("no value was found for \(type), \(context.debugDescription)")
} catch {
    print("I know not this error")
}

但这是很多代码,可以放置在任何我可能遇到解码错误的地方。而且,如果我的do {}块引发了多个调用,则可能需要处理这些方法以不同方式调用的错误。我正在尝试实现的模式如下所示:其中encodingError(error)具有上面所有的凌乱代码

do {
    let object1 = try decoder.decode(SomeClass.self, from: someData)
    try object2.methodThatThrowsSomeOtherError()
} catch <all decoding errors> {      // this is invalid pseudocode
    MyCentralLogger.log.decodingError(error)
} catch let nonDecodingError {
    MyCentralLogger.log.error(nonDecodingError)
}

我可以有一个这样的捕获模式,似乎可以满足所有枚举的情况(至少可以编译)

} catch is DecodingError {

但是编译器似乎没有自动绑定'error'变量,而且我看不到任何类似的选项

} catch let decodingError is DecodingError {  // THIS IS NOT VALID

如果我仅捕获所有错误,就可以轻松地在中央方法中进行切换,以适当地区分不同的解码错误情况。但我希望能够避免将非解码错误发送到该交换机。我还可以分离我的do {}块,以便仅在其中执行解码步骤,但这也会使代码混乱,尤其是当您解码散布有其他动作的多个消息时。

建议?谢谢大家!

2 个答案:

答案 0 :(得分:1)

catch行中使用的语法与case的{​​{1}}中使用的模式语法完全相同。如果您知道如何编写switch,那么您就会知道如何编写case

例如,您抱怨:

catch

对。但这是有效的

} catch let decodingError is DecodingError {  // THIS IS NOT VALID

哦,一个字母有什么不同?

答案 1 :(得分:0)

这仍然比预期的代码多得多,但可能更简洁:

} catch DecodingError.keyNotFound(_, let context),
        DecodingError.valueNotFound(_, let context),
        DecodingError.typeMismatch(_, let context),
        DecodingError.dataCorrupted(let context) {
    print(context.debugDescription)
    MyCentralLogger.log.decodingError(context.underlyingError)
} catch {
    print(error.localizedDescription)
    MyCentralLogger.log.error(error)
}