Вызов службы
361
let hours: String
}
Отлично! Теперь у нас есть действующий сетевой клиент, который можно
использовать для поиска библиотек. Мы
почти
закончили, осталось только за
-
действовать клиента в пользовательском интерфейсе. Вернемся к
LocationsTa
bleViewController
и добавим следующий код в наш метод
searchBarTextDidEndEdit
ing(_:)
в классе
UISearchBarDelegate
:
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
let country = searchBar.text ?? ""
locationsController.fetchLocations(for: country, completionHandler:
{ (locations) in
DispatchQueue.main.async {
self.locations =
locations
self.tableView.reloadData()
}
}) { (error) in
DispatchQueue.main.async {
self.locations = []
self.tableView.reloadData()
}
}
}
Рассмотрим этот код подробнее.
Сначала сохраняем в переменной
country
строку из свойства
text
поля ввода.
Свойство
text
имеет тип
String
, а значит, может содержать
nil
; мы исправим
эту проблему с помощью оператора
??
, который означает следующее: «если
операнд слева от оператора равен
nil
, использовать операнд справа». В дан
-
ном случае мы присваиваем пустую строку. Затем вызываем метод
fetchLoca
tions
нового свойства, добавленного в класс, которое содержит объект
Location
sController
. Мы передаем методу обработчик
completionHandler
с замыканием
errorHandler
, который сохранит полученные результаты в локальном свойстве
и обновит табличное представление, содержащееся в этом представлении.
Обратите
внимание, что для обновления представления мы посылаем из
замыканий запрос в основной поток. Мы не знаем, в каком потоке будет вы
-
полняться сетевой вызов, но все обновления пользовательского интерфейса
должны производиться только в основном потоке.
Нам осталось урегулировать еще одну проблему в этом классе, прежде чем
мы сможем его протестировать. Нам нужно, чтобы табличное представление
получило данные из массива
locations
, который в
данный момент хранится
в классе. К счастью, если вы помните, этот класс доступен в табличном пред
-
ставлении в виде свойства
dataSource
, поэтому, чтобы задействовать мас
-
сив
locations
, достаточно внести небольшие изменения в методы протокола
UITableViewDataSource
, как показано ниже:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) > Int {
return locations.count
}
362
Сетевые
операции в приложении
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) > UITableViewCell {
// Получить ячейку из
пула свободных ячеек
let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell",
for: indexPath)
// Найти местоположение, соответствующее заполняемой ячейке
let location = locations[indexPath.row]
//
Добавить оформление ячейки
cell.textLabel?.text = location.emoji
cell.detailTextLabel?.text =
"\(location.streetAddress)\n\(location.city), \(location.country)\nHours: \(location.
hours)"
return cell
}
Окончательная версия класса
LocationsViewController
должна выглядеть так:
import UIKit
class LocationsTableViewController: UITableViewController {
let locationsController = LocationsController()
var locations: [Location] = []
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
searchController.searchBar.placeholder = "Search Locations by Country"
searchController.obscuresBackgroundDuringPresentation = false
definesPresentationContext = true
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
// Источник данных для табличного представления
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) > Int {
return locations.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) > UITableViewCell {
// Получить ячейку из пула свободных ячеек
let cell = tableView.dequeueReusableCell(withIdentifier: "LocationCell",
for: indexPath)
// Найти местоположение, соответствующее заполняемой ячейке
let location = locations[indexPath.row]
// Добавить оформление ячейки
cell.textLabel?.text =
"\(location.streetAddress)\n\(location.city), \(location.country)\nHours: \(location.
hours)"
Вызов службы
363
cell.detailTextLabel?.text = location.emoji
return cell
}
}
extension LocationsTableViewController: UISearchBarDelegate {
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
let country = searchBar.text ?? ""
guard country != "" else {
self.locations = []
self.tableView.reloadData()
return
}
locationsController.fetchLocations(for: country, completionHandler:
{ (locations) in
DispatchQueue.main.async {
self.locations = locations
self.tableView.reloadData()
}
}) { (error) in
DispatchQueue.main.async {
self.locations = []
self.tableView.reloadData()
}
}
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
self.locations = []
self.tableView.reloadData()
}
}
Соберите и запустите приложение, щелкните на кнопке с лупой, выполните
поиск по
названию страны, и... на экране ничего не появится. Но почему?
Взгляните на панель консоли, там вы увидите сообщение об ошибке:
App Transport Security((("App Transport Security"))) has blocked a cleartext HTTP (http://)
resource load since it is insecure. Temporary exceptions can be configured via your
app's((("Info.plist file"))) Info.plist file.
Причина в том, что политика безопасности, устанавливаемая компанией
Apple, требует использовать URL со схемой
https://
, тогда как мы использова
-
ли схему
http://
. Эту проблему легко исправить, и фактически решение при
-
водится в самом сообщении об ошибке: нужно добавить исключение в файл
Info.plist
приложения. В этом файле находятся конфигурационные параметры
приложения.
Чтобы добавить исключение для своего домена, откройте
Info.plist
и в по
-
следней строке щелкните на кнопке
Do'stlaringiz bilan baham: