Exordium
В предыдущем посте я писал о настройке Core Location в приложении UIKit. Я рассмотрел добавление описаний использования в файл Info.plist, запрос авторизации местоположения и получение местоположения из CLLocationManager. Если вам нужна помощь в настройке Core Location в вашем приложении UIKit, взгляните на этот пост: https://rustynailsoftware.com/dev-blog/core-location-setting-up-core-location-with-uikit.
В этом посте я расскажу, как реализовать CLGeocoder - класс в Core Location, который помогает разработчикам создавать удобочитаемые версии географических координат в своих приложениях для iOS. Я также вкратце расскажу об объекте CLLocation, поскольку я не смог этого сделать в своей первой публикации Core Location. Вы можете следовать за кодом, который я разместил на GitHub: https://github.com/andrew-lundy/core-location-tutorial
Давайте погрузимся.
Класс CLLocation
Важным аспектом Core Location является класс CLLocation. Это настолько важно, что я забыл написать об этом в моем первом блоге из серии Core Location. Класс CLLocation - это объект, содержащий информацию о местоположении устройства, включая информацию о высоте и курсе. Информация о курсе - это скорость и направление устройства. В Core Location вы получаете подробные сведения о местоположении через класс CLLocationManager. Здесь я сохранил информацию в переменной currentLocation:
let locationManager = CLLocationManager() let currentLocation = locationManager.location
Благодаря этому мы получили доступ к деталям местоположения и возможность их извлекать. Например, чтобы получить координаты местоположения, используйте атрибут координаты диспетчера местоположения:
let locationManager = CLLocationManager() let currentLocation = locationManager.location // Print the location details. // Ex: <+37.78735352, -122.40822700> +/- 5.00m (speed - 1.99 mps / course - 1.00) @ 9/5/20, 5:13:46 PM Central Daylight Time print(currentLocation) let locationCoordinate = currentLocation.coordinate // Print the coordinate value of the location as a CLLocationCoordinate2D. // Ex: CLLocationCoordinate2D(latitude: 37.787353515625, longitude: -122.408227) print(locationCoordinate)
Обратное геокодирование с помощью CLGeocoder
Как видно выше, класс CLLocation возвращает информацию о местоположении в практически непригодном для использования формате. Конечно, мы можем получить географические координаты и скорость, с которой движется устройство. Но эта информация может быть полезна только в определенных ситуациях. Что происходит, когда нам нужно отображать информацию о местоположении для пользователей, которые не хотят читать и преобразовывать координаты? Ответ можно найти в классе Apple CLGeocoder.
На данный момент класс ViewController содержит следующие объекты и IBOutlets:
@IBOutlet weak var changeLocationBttn: UIButton! @IBOutlet weak var reverseGeocodeLocation: UIButton! @IBOutlet weak var locationDataLbl: UILabel! private var locationManager: CLLocationManager! private var currentLocation: CLLocation! private var geocoder: CLGeocoder!
Я собираюсь инициализировать CLGeocoder в методе viewDidLoad класса ViewController:
override func viewDidLoad() { super.viewDidLoad() changeLocationBttn.layer.cornerRadius = 10 reverseGeocodeLocation.layer.cornerRadius = 10 reverseGeocodeLocation.titleLabel?.textAlignment = .center locationManager = CLLocationManager() locationManager.delegate = self // Initialize the Geocoder geocoder = CLGeocoder() }
Вся работа, которую будет выполнять CLGeocoder, будет выполняться в методе reverseGeocodeLocationBttnTapped. Первое, что мы собираемся сделать, это убедиться, что переменная currentLocation не пуста. Он настроен для хранения информации о местоположении устройства и получает значение, когда приложение запрашивает статус авторизации. Нам нужно выполнить эту проверку, потому что нет ничего, что нужно было бы геокодировать в обратном направлении, если нет значения местоположения.
@IBAction func reverseGeocodeLocationBttnTapped(_ sender: Any) { guard let currentLocation = self.currentLocation else { print("Unable to reverse-geocode location.") return } }
Чтобы запустить процесс обратного геокодирования координат, необходимо вызвать метод reverseGeocodeLocation в CLGeocoder. Этот метод принимает два параметра - объект CLLocation и CLGeocodeCompletionHandler. Обработчик завершения также имеет два параметра - массив CLPlacemark и Ошибка.
// The method that does the reverse-geocoding. geocoder.reverseGeocodeLocation(location: CLLocation, completionHandler: CLGeocodeCompletionHandler) // Here is the method when in use. geocoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in }
Класс CLPlacemark появился недавно, поэтому давайте взглянем на него. CLPlacemark, или метка, содержит удобочитаемую версию координат и дает разработчикам доступ к такой информации, как название места, город, штат, почтовый индекс и т. Д. Вы можете узнать больше о классе CLPlacemark в документации Apple: https://developer.apple.com/documentation/corelocation/clplacemark
Вот шаги, которые мы выполним в обработчике завершения:
geocoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in // 1 if let error = error { print(error) } // 2 guard let placemark = placemarks?.first else { return } print(placemark) // Geary & Powell, Geary & Powell, 299 Geary St, San Francisco, CA 94102, United States @ <+37.78735352,-122.40822700> +/- 100.00m, region CLCircularRegion (identifier:'<+37.78735636,-122.40822737> radius 70.65', center:<+37.78735636,-122.40822737>, radius:70.65m) // 3 guard let streetNumber = placemark.subThoroughfare else { return } guard let streetName = placemark.thoroughfare else { return } guard let city = placemark.locality else { return } guard let state = placemark.administrativeArea else { return } guard let zipCode = placemark.postalCode else { return } // 4 DispatchQueue.main.async { self.locationDataLbl.text = "\(streetNumber) \(streetName) \n \(city), \(state) \(zipCode)" } }
- Проверьте, не выдает ли обработчик ошибку. Если да, распечатайте его на консоли. В реальном приложении вы справитесь с ошибкой более эффективно.
- Используйте оператор защиты, чтобы получить первую метку, возвращенную обработчиком завершения. Для большинства запросов геокодирования массив меток должен содержать только одну запись. Я пошел дальше и распечатал данные метки.
- В зависимости от варианта использования извлекайте определенные данные из метки. В данном случае я вытащил номер улицы, название улицы, город, штат и почтовый индекс.
- Наконец, я обновил метку в приложении данными метки. Поскольку это меняет пользовательский интерфейс, я сделал это в основном потоке, используя класс DispatchQueue.
IBAction reverseGeocodeLocationBttnTapped теперь должен выглядеть следующим образом:
@IBAction func reverseGeocodeLocationBttnTapped(_ sender: Any) { guard let currentLocation = self.currentLocation else { print("Unable to reverse-geocode location.") return } geocoder.reverseGeocodeLocation(currentLocation) { (placemarks, error) in if let error = error { print(error) } guard let placemark = placemarks?.first else { return } guard let streetNumber = placemark.subThoroughfare else { return } guard let streetName = placemark.thoroughfare else { return } guard let city = placemark.locality else { return } guard let state = placemark.administrativeArea else { return } guard let zipCode = placemark.postalCode else { return } DispatchQueue.main.async { self.locationDataLbl.text = "\(streetNumber) \(streetName) \n \(city), \(state) \(zipCode)" } } }
Заканчивать
Приложение теперь может запрашивать авторизацию местоположения, получать местоположение устройства и - новейшая функция - выполнять обратное геокодирование местоположения. Вот как выглядит приложение:
Спасибо, что уделили немного времени своему дню и прочитали это пошаговое руководство. Core Location - это ключ к созданию любого приложения для iOS, основанного на местоположении, и я надеюсь, что вы узнали что-то новое. Не стесняйтесь связаться со мной в Twitter и помочь развитию сообщества разработчиков iOS: https://twitter.com/andrewlundydev.
Вы можете прочитать исходную версию в моем блоге: https://rustynailsoftware.com/dev-blog/core-location-reverse-geocoding-locations-using-clgeocoder
Ресурсы:
Настройка основного местоположения с помощью UIKit: https://rustynailsoftware.com/dev-blog/core-location-setting-up-core-location-with-uikit
CLLocation Docs: https://developer.apple.com/documentation/corelocation/cllocation
Документы CLGeocoder: https://developer.apple.com/documentation/corelocation/clgeocoder
Документы CLGeocodeCompletionHandler: https://developer.apple.com/documentation/corelocation/clgeocodecompletionhandler
Документы CLPlacemark: https://developer.apple.com/documentation/corelocation/clplacemark
Документы DispatchQueue: https://developer.apple.com/documentation/dispatch/dispatchqueue