Ugly Swift Syntax for Checking Errors
Posted on
A common code pattern I see a lot in iOS code is:
service.execute(request) { (response, error) in
if let error = error {
handleError(error)
return
}
// work with response...
}
I don’t like that if
statement. I’d much rather use a guard
statement.
For those who don’t know guard
, the docs explain:
A
guard
statement, like anif
statement, executes statements depending on the Boolean value of an expression. You use aguard
statement to require that a condition must be true in order for the code after the guard statement to be executed.
I like guard
over if
cause it’s more expressive about my intentions that the code after it should only run if there was no error found. Unfortunately, because of the boolean nature of the guard
clause, to do this requires using Implicitly Unwrapped Optionals.
service.execute(request) { (response, error) in
guard error == nil else {
handleError(error!)
return
}
// work with response...
}
I really try to avoid Implicitly Unwrapped Optionals, so much so I use SwiftLint to throw warnings for their use. Adding lint exceptions for this regular occurrence, for me, is not an option.
If you have more control over the service
implementation you might choose to use a Result
type.
enum Result<T> {
case success(T)
case failure(Error)
}
service.execute(request) { (result) in
switch result {
case .failure(let error):
handleError(error)
case .success(let response):
handleResponse(response)
}
}
I generally like this but it doesn’t work if you need to support a mixed Swift/Objective-C environment. It also doesn’t account UIKit itself does not use a Result type.
Code should be beautiful and so I think it’s important to document these things. I’d love to find a better solution and welcome feedback.