Я рефакторинг своего кода, чтобы сделать все чище. Я делаю запрос к своему API и могу ожидать различные типы возвращаемых значений, поэтому я создал общую функцию, чтобы упростить свой код.
Я хотел, чтобы эта функция вызывала исключение, чтобы я мог просто использовать do catch
для обработки ошибок или успешных случаев с разными типами.
Это моя функция:
func performRequest<T: Codable>(_ request: URLRequest, ofType: T.Type) throws -> T{
URLSession.shared.dataTask(with: request) {(data, response, err) in
if let err = err {throw err}
if let response = response as? HTTPURLResponse {
if response.statusCode != 200 {
// Here I would return the value
} else {
// here I would throw the error
}
}
}.resume()
}
Но в первой строке после URLSession.shared.dataTask
я получил эту ошибку:
Invalid conversion from throwing function of type '(_, _, _) throws -> ()' to non-throwing function type '(Data?, URLResponse?, Error?) -> Void'
Я понимаю, что это потому, что я пытаюсь использовать функцию dataTask внутри, но мой вопрос в том, есть ли способ сделать это?
Ваш звонок асинхронный. Вам необходимо вернуть данные в закрытии после получения данных. Для проверки успешности вызова вы можете использовать недавно введенный тип Result
, так что вам не нужно throw
func performRequest<T: Codable>(_ request: URLRequest, completion: @escaping (Result<T, Error>) -> Void) {
URLSession.shared.dataTask(with: request) { (data, response, err) in
if let err = err {
return completion(Result.failure(err))
}
if let response = response as? HTTPURLResponse {
if response.statusCode == 200 { // 200 is code for OK btw
return completion(Result.success(someValueOfTypeT))
} else {
return completion(Result.failure(yourError))
}
}
}.resume()
}
Использование: (обратите внимание, что тип T
можно вывести из объявления закрытия)
performRequest(someRequest) { (result: Result<SomeTypeConformsToCodable, Error>) in
switch result {
case .success(let value):
// work with value
case .failure(let err):
print(err)
}
}
Роберт Дреслер, большое спасибо за ваш ответ, я попробовал этот подход с использованием функции выбрасывания, потому что я вызываю эту функцию внутри другой функции, которая также принимает завершениеHandler с параметром типа Result, поэтому я подумал, что выбрасывание будет чище для чтения, как только я пришлось бы отправить результат внутри другого результата, теперь я понимаю, что это правильный путь... спасибо
Вы не можете
throw
внутри обработчика завершенияURLSession.shared.dataTask
, потому что тип этого обработчика завершения уже определен, и он не являетсяthrows
функцией.