Вызов службы
359
Здесь сначала создается URL с адресом нашей службы поиска. В настоящее
время служба доступна по адресу
ht
tp://localhost:3000/locatio
n
, если вы следо
-
вали за примером создания службы Node выше в этой главе, в противном случае
используйте любой другой URL, уместный здесь. Инициализатор
URL(string:)
генерирует объект
URL
, поддерживающий пустое значение, то есть экземпляр
типа
URL?
. Мы принудительно распаковываем с использованием оператора
!
,
потому что точно знаем, что он не будет содержать пустого значения. (Но даже
если это произойдет, для нас предпочтительнее узнать об этом, получив ава
-
рийное завершение приложения!)
Далее используется свойство
shared
класса
URLSession
, чтобы получить доступ
к разделяемому сеансу и сгенерировать экземпляр
URLSessionDataTask
вызовом
метода
dataTask(with:completionHandler:)
– мы нигде не создаем экземпляры
URL
SessionDataTask
непосредственно. Полученный экземпляр сохраняется в пере
-
менной
task
.
Обработчик завершения имеет три параметра:
data
,
response
и
error
. Пара
-
метр
data
имеет тип
Any?
и содержит данные, полученные в ответе. Параметр
response
содержит экземпляр ответа типа
URLResponse
, а параметр
error
, содер
-
жащий экземпляр
Error?
, используется для проверки успешного выполнения
запроса.
Прямо сейчас наш метод
fetchLocations(for:completionHandler:errorHandler)
уже сможет послать запрос службе, но, поскольку замыкание с обработчиком
завершения имеет пустое тело, ничего не произойдет. Давайте исправим это.
Вот как должно выглядеть полное тело нашего метода:
func fetchLocations(for country: String,
completionHandler: @escaping ([Location]) -> (),
errorHandler: @escaping (Error?) > ()) {
let url = URL(string: "http://localhost:3000/locations?country=\(country)")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
// Возникла
ошибка на стороне сервера
errorHandler(error)
return
}
guard let response = response as? HTTPURLResponse,
response.statusCode < 300 else {
// Возникла ошибка на стороне клиента
errorHandler(nil)
return
}
guard let data = data else {
// Получены
недействительные данные
errorHandler(nil)
return
}
// Преобразовать данные в массив [Location]
}
task.resume()
}
360
Сетевые операции в приложении
В теле
dataTask(with:completionHandler:)
мы передаем замыкание, которое:
1) проверяет наличие
ошибки на стороне сервера, анализируя параметр
error
. Если произошла ошибка, вызывается замыкание
errorHandler
, и за
-
тем управление возвращается приложению;
2) если на стороне сервера никаких ошибок не возникло (то есть
error
со
-
держит значение
nil
), проверяется код состояния HTTP-ответа – он дол
-
жен быть меньше
300
. Если это не так, снова
вызывается
errorHandler
, но
этот раз, так как
error
содержит значение
nil
, мы передаем обработчику
nil
;
3) если сетевая операция завершилась успешно, проверяются полученные
данные. Объект
data
должен быть непустым. Если данные отсутствуют,
снова вызывается
errorHandler
с параметром
nil
.
Теперь возьмем этот объект с данными и преобразуем содержащийся в нем
документ JSON в массив объектов
Location
. После добавления необходимого
кода
получаем следующий файл
Do'stlaringiz bilan baham: