Обратное геокодирование на выводе

#swift #maps

#swift #Карты

Вопрос:

Я не могу понять, как отображать адрес улицы, город и т.д. В качестве субтитра на pin-коде, используя обратное геокодирование — всякий раз, когда пользователь добавляет PIN-код. Пока это мой код. Я предположил, что мне нужно написать «annotation.subTitle = CLLocationCoordinate2D», чтобы отобразить его на выводе, но, похоже, это не работает. Что мне делать? Снимок экрана 1

Комментарии:

1. Трудно понять, где вы могли бы застрять здесь, что вы пробовали? Что результат, который вы видите, говорит вам о том, что происходит? Для начала у вас, похоже, есть reverseGeocodeLocation функция, которая никогда не вызывается.

2. @Jonah Я новичок в кодировании, поэтому я все еще вроде как учусь, как что-то делать. Как мне нужно это вызвать? Я думал, что то, что я делал, в значительной степени активировало субтитры для чтения на pin-коде уличного адреса пользователя.

Ответ №1:

Похоже, что здесь есть некоторая путаница в синтаксисе Swift, поэтому я попытаюсь разобраться с этим и посмотреть, приведет ли это к решению проблемы, которую вы пытаетесь решить. Пожалуйста, простите меня, если я объясняю код, который вы уже понимаете.

Чтение примера кода:

Для начинающих я вижу объявление функции:

 func action(gestureRecognizer: UIGestureRecognizer) { ...
  

Здесь у нас есть функция с именем action с одним аргументом с именем gestureRecognizer , который является UIGestureRecognizer . Я предполагаю, что где-то, не показанное в вопросе, было создано UIGestureRecognizer , которое вызовет эту функцию при обнаружении соответствующего жеста.

В action функции мы выводим «Распознанный жест» на консоль. Я предполагаю, что вы увидите это, если запустите это приложение и выполните соответствующий жест в соответствующем представлении.

Затем мы получаем местоположение жеста и сохраняем его в локальной константе с именем touchPoint . Если мы посмотрим на ссылку на класс UIGestureRecognizer, мы увидим, что UIGestureRecognizer ‘s location возвращает CGPoint тип, который является «Точкой в локальной системе координат зрения, которая идентифицирует местоположение жеста».. Опять же, пока все хорошо, похоже, что мы обнаруживаем жест и определяем, где в некотором представлении произошел жест, возможно, касание.

Теперь это несколько сбивает с толку:

 func reverseGeocodeLocation(_ location: CLLocation, completionHandler: @escaping CLGeocodeCompletionHandler)
  

объявляет новую вложенную функцию с именем reverseGeocodeLocation . Это не так уж плохо автоматически, возможно, вы захотите создать вложенную функцию для определения некоторого повторно используемого поведения (есть обсуждение вложенной функции на языке программирования Swift). Однако в данном случае это, похоже, копия существующего метода из CLGeocoder , и я подозреваю, что то, что вы хотите сделать, это вызвать эту существующую функцию, а не определять новую функцию с тем же именем с совершенно несвязанным поведением.

Затем у нас есть блок кода, предоставленный в качестве тела функции этой вложенной функции. Как показано, эта reverseGeocodeLocation вложенная функция никогда не вызывается, поэтому этот код никогда не выполняется. Мне кажется, что это должен быть обработчик завершения, переданный CLGeocoder ‘s reverseGeocodeLocation , который затем будет выполняться, как только местоположение будет геокодировано в обратном направлении.

Решение проблемы (частично)

Для вызова CLGeocoder существующей функции нам нужно получить экземпляр CLGeocoder . Это метод экземпляра, нам нужна ссылка на некоторый существующий объект геокодера, для которого мы можем вызвать эту функцию. Затем нам нужно создать допустимый набор аргументов для передачи reverseGeocodeLocation .

Глядя на ссылку на класс CLGeocoder , у него нет пользовательских инициализаторов, нам не нужно предоставлять ему какие-либо данные для создания экземпляра, поэтому мы можем просто вызвать CLGeocoder()

Рассматривая reverseGeocodeLocation , мы видим немного сложный набор аргументов:

 func reverseGeocodeLocation(_ location: CLLocation, completionHandler: @escaping CLGeocodeCompletionHandler)
  

Мы должны передать reverseGeocodeLocation два аргумента. location это CLLocation , это не так уж плохо, мы можем построить один из них из пары координат, поэтому я уверен, что есть способ преобразовать местоположение наших touchPoint экранных координат в широту и долготу. completionHandler это CLGeocodeCompletionHandler , это немного сложнее, это замыкание, которое фиксирует некоторое поведение и предоставляет два собственных аргумента.

Давайте попробуем это на игровой площадке Xcode, прежде чем пытаться добавить его в приложение:

 import CoreLocation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true // We're using asynchronous behavior here so we need this to tell the Playground to keep running until our reverse geocoding finishes rather than stopping immediately when it reaches the end of our example code.
let location = CLLocation(latitude: 37.332112, longitude: -122.0329646) // Somewhere near Apple HQ should geocode successfully
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
    print(placemarks?.first?.name)
    PlaygroundPage.current.finishExecution() // Now that our async task has completed we can tell the playground that it is time to stop running.
}
  

Почти готово

Теперь мы увидели, как геокодировать местоположение, чтобы мы могли добавить это поведение в наше приложение. Мы должны решить 2 проблемы, чтобы это произошло.

  1. Нам нужно не только создать CLGeocoder для выполнения обратного геокодирования, но и сохранить его до завершения. Если мы просто создадим геокодер в нашей action функции, то функция завершится, и геокодер может быть уничтожен до того, как он успеет завершить геокодирование. Одним из способов решения этой проблемы было бы добавить геокодер в качестве свойства контроллера представления (или любого другого класса), который содержит эту action функцию, чтобы геокодер существовал до тех пор, пока объект его использует.
  2. Нам нужно преобразовать координаты вида нашего touchPoint в CLLocation . Если мы касаемся, MKMapView то его convert функция может быть именно тем, что нам нужно.