Short story: You can't throw
in a dataTask
completion closure
You could return two values in the completion handler
...completion: @escaping (ResultType?, Error?)->Void
and return
completion(result, nil)
completion(nil, CustomError.myerror)
or more convenient use an enum with associated type
enum Result {
case success(ResultType), failure(Error)
}
...completion: @escaping (Result)->Void
and return
completion(.success(result))
completion(.failure(CustomError.myerror))
You can process the result
foo() { result in
switch result {
case .success(let resultType): // do something with the result
case .failure(let error): // Handle the error
}
}
Update:
In Swift 5 using the new built-in Result
type it's even more comfortable because Result
can capture the result of the throwing expression
...completion: @escaping (Result<MyType,Error>)->Void
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) in
completion(Result { try something()})
})
task.resume()
Update 2:
With async/await
completion handlers are gone
do {
let (data, response) = try await URLSession.shared.data(for: request)
} catch {
throw CustomError.myerror
}