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!
This indicates that the method may raise an error and as a best practice, you should gracefully handle the error and show an appropriate error message to the user. If you don’t catch the error, then your app will crash! Here’s an example of the Swift do-try-catch syntax:
Swift Try Catch When you’re coding, you’ll see methods that have the throws keyword. This indicates that the method may raise an error and as a best practice, you should gracefully handle the error and show an appropriate error message to the user. If you don’t catch the error, then your app will crash!
Error handling in Swift interoperates with error handling patterns that use the NSError class in Cocoa and Objective-C. For more information about this class, see Handling Cocoa Errors in Swift. In Swift, errors are represented by values of types that conform to the Error protocol.
An expression pattern represents the value of an expression. Expression patterns appear only in switch statement case labels. The expression represented by the expression pattern is compared with the value of an input expression using the Swift standard library ~= operator. The matches succeeds if the ~= operator returns true.
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.
This is still a lot more code than desired, but maybe a little bit cleaner:
} 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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With