Using Swift 4.2 and XCode 10
In Swift 4.2, DecodingError is an enumeration. There are (currently) four different cases. I can catch each case separately, and bind variables that I can use to log the error as in the following code ...
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")
}
But this is a lot of code to put everywhere I could encounter a decoding error. And, if my do{} block has multiple calls that throw, I may need to handle the errors that those methods call differently. The pattern I am trying to implement looks like this ... where decodingError(error) has all of the messy code above
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)
}
I can have a catch pattern like this that seems to satisfy all of the enumeration cases (at least it compiles)
} catch is DecodingError {
but the compiler doesn't seem to autobind the 'error' variable, and I don't see any option like
} catch let decodingError is DecodingError { // THIS IS NOT VALID
If I just catch all errors, I can easily have a switch in a central method that separates the different decoding error cases appropriately. But I want to be able to avoid sending non-decoding errors into that switch. I can also separate my do{} blocks so that I'm only performing decoding steps in it, but this also makes code messy, particularly if you are decoding multiple messages interspersed with other actions.
Suggestions? Thanks all!
The syntax used in a catch
line is exactly the same pattern syntax used in the case
of a switch
. If you know how to write a case
you know how to write a catch
.
So, for example, you complain:
} catch let decodingError is DecodingError { // THIS IS NOT VALID
Right. But this is valid:
} catch let decodingError as DecodingError {
Oh what a difference one letter makes.