11

使用 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{} 块有多个抛出的调用,我可能需要处理这些方法以不同方式调用的错误。我试图实现的模式看起来像这样......其中 decoderError(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 {

但编译器似乎没有自动绑定“错误”变量,而且我没有看到任何类似的选项

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

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

建议?谢谢大家!

4

3 回答 3

26

一行中使用的语法与 a中catch使用的模式语法完全相同。如果你知道怎么写 a你就知道怎么写.caseswitchcasecatch

因此,例如,您抱怨:

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

对。但这有效的:

} catch let decodingError as DecodingError { 

哦,一封信有多大的不同。

于 2019-01-02T17:22:25.690 回答
1

这仍然比预期的要多得多,但可能更简洁一些:

} 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)
}
于 2021-01-08T17:24:08.827 回答
0

结合有效答案和switch陈述,以下内容将为您节省一些几乎相同的行:

do {
    let model = try jsonDecoder.decode(BattleShip.self, from: jsonData!)
    print(model)
} catch let decodingError as DecodingError {
    switch decodingError {
    case .typeMismatch(_, let c), .valueNotFound(_, let c), .keyNotFound(_, let c), .dataCorrupted(let c):
        print(c.debugDescription)
    }
} catch {
    print(error.debugDescription)
}

如果,fi,您的解码数据错过了该属性index: Int,它将打印

没有与键 CodingKeys(stringValue: "index", intValue: nil) ("index") 关联的值。

对于调试目的,这应该足够清楚。

于 2022-02-17T15:52:28.923 回答