Продолжаем перевод главы. Первая часть перевода.
Теперь откройте RestaurantDetailViewController.swift. Напомню, мы
настроили MapKit framework в проекте и теперь должны добавить оператор импорта
для того, чтобы использовать его. Итак, сначала добавим строку кода в самом
начале, чтобы импортировать MapKit.

import MapKit

Затем надо объявить Оutlet переменную для MapView:

@IBOutlet var mapView: MKMapView!

Чтобы использовать UITapGestureRecognizer для обнаружения нажатия, вам нужно
будет инициализировать объект UITapGestureRecognizer и прикрепить его к карте.
Вставьте следующий код в методе viewDidLoad():

let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showMap))
mapView.addGestureRecognizer(tapGestureRecognizer)

Во время инициализации мы ссылаемся через UITapGestureRecognizer на метод
вызова, которым является функция showMap. Мы еще не реализовали метод
showMap, так что добавьте этот код в класс RestaurantDetailViewController.

func showMap() {
    performSegue(withIdentifier: "showMap", sender: self)
}

Этот метод прост, мы программно вызываем showMap через seque путем вызова
preformSeque с идентификатором, который указывали при создании seque
ранее. Теперь, когда пользователь вводит вид карты в таблице, будет вызываться метод showMap().
Следовательно, showMap срабатывает.

И, наконец, вернемся к Main.Storyboard и установим связь между картой (в
колонтитуле таблицы) и mapView Outlet.

Установим связь между картой и mapView Outlet

Если вы скомпилируйте и запустите приложение, нажмите на карту в
RestaurantDetailViewController. Приложение должно перейти к полной
функциональной карте.

Преобразование адреса в координаты с помощью Geocoder

Теперь вы знаете, как вставлять карту в приложение, но как вы можете закрепить
местоположение на карте?

Для того, чтобы выделить место на карте, вы не можете использовать физический
адрес. MapKit framework не работает так. Вместо того, карта должна знать
географические координаты, выраженные в терминах широты и долготы соответствующей
точки на земном шаре.

В фреймворке имеется класс Geocoder для разработчиков, чтобы преобразовать
текстовый адрес, известные как метки, в глобальную координату. Этот процесс обычно
называют вперед-геокодирование. С другой стороны, вы можете использовать
Geocoder для преобразования широты и долготы значения, обратно в метки.
Этот процесс известен как обратное-геокодирование.

Для того, чтобы инициировать запрос вперед-геокодирование с помощью класса
CLGeocoder, все, что вам нужно сделать, это создать экземпляр CLGeocoder,
а затем вызвать метод geocodeAddressString с параметрами адреса. Вот пример:

let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString("524 Ct St, Brooklyn, NY 11231",
completionHandler: { placemarks, error in
// Process the placemark
})

Там не назначен формат адреса. Метод представляет указанные данные о
местоположении на сервер геокодиронивания асинхронно. Затем сервер анализирует
адрес и возвращает вам массив объектов. Количество объектов возвращается
в зависимости от адреса. Чем точнее адрес, который вы дали, тем лучше
результат. Если ваш адрес не является достаточно конкретным, вы можете в
конечном итоге получить ответ от сервера с несколькими объектами.

C помощью объекта, который является экземпляром класса CLPlacemark, вы можете
легко получить географические координаты адреса, используя следующий код:

let coordinate = placemark.location?.coordinate

Обработка в этом блоке кода будет выполняться после того, как запрос
вперед-кодирование завершается. Операции, как аннотирования метки будет
сделано в блоке кода.

Краткий обзор добавления аннотации на карте

Теперь, когда у вас есть общее представление о Geocoder, как получить
глобальные адреса, мы посмотрим на то, как можно закрепить местоположение
на картах. Чтобы сделать это, в Mapkit встроенна аннотация для вас, чтобы
определить конкретное место.

Карта с аннотацией

Аннотации могут быть в разных формах. Пин и аннотацию вы обычно видите
в своем приложении. Обычно аннотация состоит из изображения и выноски,
которая отображает дополнительную информацию о местоположении.

С точки зрения разработчика аннотация на самом деле состоит из двух различных
объектов:

  • Объект — хранит данные аннотации, такие как, метки. Объект должен соответствовать протоколу MKAnnotation, как это определенно в MapKit.
  • Вид — является фактическим объектом для визуального представления аннотаций. Пин изображения является примером. Если вы хотите отобразить аннотацию в своей собственной форме (скажем, использовать карандаш заместо пина), вам необходимо создать свой собственный вид аннотации.

MapKit поставляется со стандартной аннотацией и пояснительной. Так, что вам
не нужно создавать свою собственную, если вы не хотите, чтобы потом настраивать
аннотацию. В простейшей форме, в стандартной аннотации появляется пин без
изображений и выноски. Чтобы добавить пин на карте, вам просто нужно несколько строк кода:

let annotation = MKPointAnnotation()
if let location = placemark.location {
    annotation.coordinate = location.coordinate
    mapView.addAnnotation(annotation)
}

Класс MKPointAnnotation является стандартным классом, который принимает
протокол MKAnnotation. Указав координаты в объекте аннотаций, вы можете
вызвать метод addAnnotation объекта mapView и поставить пин на карте.

Добавление аннотаций к неинтерактивной карте

После введения вас в основы аннотирования и геокодирования, давайте вернемся к проекту
FoodPin. Сначала мы добавим в пин аннотацию к неинтерактивной карте в таблице.

В файле RestaurantDetailViewController.swift, вставьте следующий код
в метод viewDidLoad():

let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(restaurant.location, completionHandler: {
placemarks, error in
    if error != nil {
        print(error)
return
}
    if let placemarks = placemarks {
        // Get the first placemark
        let placemark = placemarks[0]
        // Add annotation
        let annotation = MKPointAnnotation()
        if let location = placemark.location {
            // Display the annotation
            annotation.coordinate = location.coordinate
            self.mapView.addAnnotation(annotation)
            // Set the zoom level
            let region =
MKCoordinateRegionMakeWithDistance(annotation.coordinate, 250, 250)
            self.mapView.setRegion(region, animated: false)
        }
} })

Я не буду объяснять код, который опубликован выше по каждой строке, как
мы обсуждали использование геокодером и аннотацией ранее. Короче говоря,
сначала мы преобразуем адрес выбранного ресторана(т.е. restaurant.location)
в координаты с использованием Geocoder. В большинстве случаев массив меток
должен содержать одну запись. Таким образом, мы просто выбираем первый элемент
из массива, с последующим отображением аннотации на карте.

Последние две строки кода являются новыми для вас. Здесь мы используем функцию
MKCoordinateRegionMakeWithDistance для регулировки начального уровня
масштабирования карты до радиуса 250 метров.

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

Если вы запустите приложение сейчас, оно должно правильно отображать
местоположение ресторана на карте.

Ссылка на проект.

Отображение пина на картер

Завершающее продолжение в следующей части перевода.
Ссылка на вторую часть. Ссылка на третью часть.

Перевод главы из книги: Beginning iOS 10 Programming with Swift 3

Автор книги: Simon Ng