#swift #closures #throw
#swift #замыкания #бросить
Вопрос:
Я рефакторингую свой код, чтобы сделать все чище. Я делаю запрос к своему 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
я получил эту ошибку:
Недопустимое преобразование из функции выбрасывания типа ‘(_, _, _) throws -> ()’ в тип функции без выбрасывания ‘(Данные?, URLResponse?, Ошибка?) -> Void’
Я понимаю, что это потому, что я пытаюсь вставить функцию dataTask внутрь, но мой вопрос в том, есть ли какой-либо способ выполнить это?
Комментарии:
1. Вы не можете
throw
внутри обработчика завершенияURLSession.shared.dataTask
, потому что тип этого обработчика завершения уже определен, и это неthrows
функция.
Ответ №1:
Ваш вызов является асинхронным. Вам нужно вернуть данные в замыкание после получения данных. Для проверки, был ли вызов успешным или нет, вы можете использовать недавно введенный 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)
}
}
Комментарии:
1. Роберт Дреслер большое вам спасибо за ваш ответ, я попробовал этот подход с использованием функции throwing, потому что я вызываю эту функцию внутри другой функции, которая также принимает completionHandler с параметром типа Result , поэтому я подумал, что выбрасывание будет удобнее для чтения, как только мне придется отправлять результат внутри другого результата, теперь я понимаю, что это правильный путь … спасибо