I created a method that uses Swift.Result
to return an image and an Error from a URLSession. I also created an Enum
for the errors.
When a Swift.Result
error is returned, how can I tell the difference between the 4 enums?
fetchImage(with: url) { (result) in
switch result {
case .failure(let err):
print(err)
// how can I determine which of the 4 enum errors was returned?
/* Example
if failErr { ... }
if responseStatusCodeErr { ... }
if dataIsNil { ... }
if catchErr { ... }
*/
case .success(let img):
// ...
}
}
Enum:
enum SessionDataTaskError: Error {
case failErr(Error)
case responseStatusCodeErr(Int)
case dataIsNil
case catchErr(Error)
}
URLSession:
fetchImage(with url: URL, completion: @escaping (Swift.Result<[UIImage], Error>)->Void) {
URLSession.shared.dataTask(with: url) { (data, res, error) in
if let error = error {
completion(.failure(SessionDataTaskError.failErr(error)))
return
}
if let response = res as? HTTPURLResponse {
guard 200 ..< 300 ~= response.statusCode else {
completion(.failure(SessionDataTaskError.responseStatusCodeErr(response.statusCode)))
return
}
}
guard let data = data else {
completion(.failure(SessionDataTaskError.dataIsNil))
return
}
do {
// all good ...
} catch {
completion(.failure(SessionDataTaskError.catchErr(error)))
}
}.resume()
}
CodePudding user response:
First, I would change your completion handler to only take SessionDataTaskError
as the error type of the Result
, because you never call it with any other types of Error
:
func fetchImage(with url: URL,
completion: @escaping (Swift.Result<[UIImage], SessionDataTaskError>)->Void) {
Then, you can use pattern matching to match the 4 cases of errors:
fetchImage(with: url) { (result) in
switch result {
case .failure(let error):
print(error)
switch error {
case .failErr:
// ...
case .responseStatusCodeErr:
// ...
case .dataIsNil:
// ...
case .catchErr:
// ...
}
case .success(let img):
// ...
}
}
If in every case you do different things, you can avoid the nested switch by doing:
fetchImage(with: url) { (result) in
switch result {
case .failure(.failErr):
// ...
case .failure(.responseStatusCodeErr):
// ...
case .failure(.dataIsNil):
// ...
case .failure(.catchErr):
// ...
case .success(let img):
// ...
}
}
If there are different types of errors that fetchImage
can produce and you just want to check for the four SessionDataTaskError
s, you can use a type pattern let error as SessionDataTaskError
, and add an extra case to handle other kinds of errors.
fetchImage(with: url) { (result) in
switch result {
case .failure(let error as SessionDataTaskError):
print(error)
switch error {
case .failErr:
// ...
case .responseStatusCodeErr:
// ...
case .dataIsNil:
// ...
case .catchErr:
// ...
}
case .failure(let otherError):
print("Other Error:", otherError)
case .success(let img):
// ...
}
}