Добавьте карту в свое приложение iOS (Swift)

1. Прежде чем начать

В этой лабораторной работе вы научитесь использовать платформу Google Карт для создания приложений для iOS на Swift. Вам предстоит создать приложение для iOS, которое будет выполнять следующие функции:

  • Загружает Maps SDK для iOS и библиотеку утилит Maps SDK для iOS.
  • Отображает карту с центром в Сиднее, Австралия.
  • Отображает пользовательские маркеры для 100 точек вокруг Сиднея.
  • Реализует кластеризацию маркеров.
  • Позволяет пользователю взаимодействовать с картой, центрируя ее и рисуя круг при нажатии на маркер.

Карта с маркерами в приложении для iOS

Предпосылки

  • Базовые знания Swift и разработки под iOS.

Что ты будешь делать?

  • Загрузите Maps SDK для iOS и библиотеку утилит Google Maps SDK для iOS.
  • Загрузите карту.
  • Используйте маркеры, пользовательские маркеры и кластеризацию маркеров.
  • Работайте с системой событий Maps SDK для iOS для поддержки взаимодействия с пользователем.
  • Управляйте камерой карты программно.
  • Нарисуйте на карте.

Что вам понадобится

Для выполнения этой лабораторной работы вам понадобятся следующие учетные записи, сервисы и инструменты:

  • Xcode 12.0 или выше с целевым SDK 12.0 или выше.
  • Cocoapods установлены.
  • Учетная запись Google Cloud Platform с включенным выставлением счетов (см. следующий шаг).
  • Проект в Cloud Console с включенным Maps SDK для iOS (см. следующий шаг).

2. Настройте

Для выполнения шага включения, описанного ниже, вам необходимо включить Maps SDK для iOS .

Настройте платформу Google Карт

Если у вас еще нет учетной записи Google Cloud Platform и проекта с включенным выставлением счетов, ознакомьтесь с руководством « Начало работы с Google Maps Platform», чтобы создать учетную запись для выставления счетов и проект.

  1. В Cloud Console щелкните раскрывающееся меню проектов и выберите проект, который вы хотите использовать для этой кодовой лаборатории.

  1. Включите API и SDK платформы Google Карт, необходимые для этой лабораторной работы, в Google Cloud Marketplace . Для этого следуйте инструкциям в этом видео или в этой документации .
  2. Сгенерируйте ключ API на странице «Учётные данные» в Cloud Console. Вы можете следовать инструкциям в этом видео или в этой документации . Для всех запросов к платформе Google Карт требуется ключ API.

Быстрый старт

Чтобы вы могли приступить к работе как можно быстрее, вот несколько начальных фрагментов кода, которые помогут вам освоить эту практическую работу.

  1. Клонируйте репозиторий, если у вас установлен git .
git clone https://github.com/googlemaps/codelab-maps-platform-101-swift.git

Или нажмите «Дайте мне код» , чтобы загрузить исходный код.

  1. После загрузки кода откройте проект StarterApp в каталоге /starter . Этот проект содержит базовую файловую структуру, необходимую для выполнения лабораторной работы. Всё необходимое для работы находится в каталоге /starter/StarterApp .

Чтобы увидеть полный работающий код решения, просмотрите завершенный код в каталоге /solution/SolutionApp .

3. Установите Maps SDK для iOS

Первый шаг к использованию Maps SDK для iOS — установка необходимых зависимостей. Этот процесс состоит из двух этапов: установка Maps SDK для iOS и библиотеки утилит Maps SDK для iOS из менеджера зависимостей Cocoapods, а также предоставление ключа API для SDK.

  1. Добавьте Maps SDK для iOS и библиотеку служебных программ Maps SDK для iOS в Podfile .

В этой лабораторной работе используются как Maps SDK для iOS, который предоставляет все основные функции Google Maps, так и библиотека утилит Maps iOS, которая предоставляет множество утилит для обогащения вашей карты, включая кластеризацию маркеров.

Для начала в Xcode (или предпочитаемом вами текстовом редакторе) откройте Podfile и обновите файл, включив в него зависимости Maps SDK для iOS и Utility Library под комментарием # Pods for StarterApp :

pod 'GoogleMaps', '6.1.0'
pod 'Google-Maps-iOS-Utils', '3.4.0'

Проверьте документацию по версиям Maps SDK для iOS на наличие последней версии SDK и рекомендаций по обслуживанию.

Ваш Podfile должен выглядеть так:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '12.0'

target 'StarterApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for StarterApp
  pod 'GoogleMaps', '6.1.0'
  pod 'Google-Maps-iOS-Utils', '3.4.0'
end
  1. Установите модули Maps SDK для iOS и Maps SDK для iOS Utility Library.

Чтобы установить зависимости, выполните команду pod install в каталоге /starter из командной строки. Cocoapods автоматически загрузит зависимости и создаст StarterApp.xcworkspace .

  1. После установки зависимостей open StarterApp.xcworkspace из каталога /starter , чтобы открыть файл в Xcode, а затем запустите приложение в симуляторе iPhone, нажав Command+R . Если всё настроено правильно, симулятор запустится и покажет чёрный экран. Не волнуйтесь, вы ещё ничего не собрали, так что это ожидаемо!
  2. Импортируйте SDK в AppDelegate.swift .

Теперь, когда все зависимости установлены, пора предоставить ключ API для SDK. Первым шагом будет импорт Maps SDK для iOS в качестве зависимости, добавив следующее под оператором import UIKit :

import GoogleMaps
  1. Передайте свой ключ API в iOS SDK, вызвав provideAPIKey для GMSServices в application: didFinishLaunchingWithOptions:
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.
    GMSServices.provideAPIKey("YOUR_API_KEY")

    return true
  }

Ваш обновленный файл AppDelegate.swift теперь должен выглядеть так:

import UIKit
import GoogleMaps

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Override point for customization after application launch.
    GMSServices.provideAPIKey("YOUR_API_KEY")

    return true
  }

}

Замените YOUR_API_KEY на ключ API, созданный вами в Cloud Console.

Теперь, когда все зависимости установлены и предоставлен ключ API, вы готовы начать совершать вызовы к Maps SDK для iOS.

4. Отобразить карту

Пришло время показать вашу первую карту!

Наиболее часто используемой частью Maps SDK для iOS является класс GMSMapView , который предоставляет множество методов, позволяющих создавать экземпляры карт и управлять ими. Вот как это реализовано:

  1. Откройте ViewController.swift .

Здесь вы выполните оставшуюся часть работы для этой лабораторной работы. Обратите внимание, что события жизненного цикла loadView и viewDidLoad для контроллера представления уже реализованы заглушками.

  1. Импортируйте Maps SDK для iOS, добавив следующее в начало файла:
import GoogleMaps
  1. Объявите переменную экземпляра ViewController для хранения GMSMapView .

Экземпляр GMSMapView — основной объект, с которым вы будете работать в этой практической работе. Вы будете ссылаться на него и работать с ним из различных методов жизненного цикла контроллера представления. Чтобы сделать его доступным, обновите реализацию ViewController , объявив переменную экземпляра для его хранения:

class ViewController: UIViewController {

  private var mapView: GMSMapView!

  ...
}
  1. В loadView создайте экземпляр GMSCameraPosition .

GMSCameraPosition определяет центр карты и отображаемый уровень масштабирования. Этот код вызывает метод cameraWithLatitude:longitude:zoom: чтобы центрировать карту на Сиднее, Австралия, с координатами широты -33,86 и долготы 151,20, с уровнем масштабирования 12:

let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 12)
  1. В loadView создайте экземпляр GMSMapView для создания карты.

Чтобы создать новый экземпляр карты, вызовите GMSMapView(frame: CGRect, camera: GMSCameraPosition) . Обратите внимание, что фрейму присваивается значение CGRect.zero — глобальная переменная из библиотеки iOS CGGeometry , которая задаёт фрейм шириной 0 и высотой 0, расположенный в позиции (0,0) внутри контроллера представления. Камера устанавливается в только что созданное вами положение.

Затем, чтобы отобразить карту, установите корневое представление контроллера представления на mapView , что позволит отобразить карту на весь экран.

    mapView = GMSMapView(frame: .zero, camera: camera)
    self.view = mapView
  1. Установите GMSMapViewDelegate для контроллера представления.

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

Сначала обновите интерфейс ViewController , чтобы он соответствовал протоколу GMSMapViewDelegate:

class ViewController: UIViewController, GMSMapViewDelegate

Затем добавьте следующую строку в функцию loadView , чтобы установить GMSMapViewDelegate для ViewController .

    mapView.delegate = self

Теперь перезагрузите приложение в симуляторе iOS ( Command+R ), и карта должна выглядеть так, как показано на следующем снимке экрана:

Приложение iOS, отображающее карту Google

Рисунок 1. Приложение iOS, отображающее карту Google.

Напомним, что на этом этапе вы создали экземпляр GMSMapView для отображения карты с центром в городе Сидней, Австралия.

Теперь ваш файл ViewController.swift должен выглядеть так:

import UIKit
import GoogleMaps

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!

  override func loadView() {

    // Load the map at set latitude/longitude and zoom level
    let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)

    mapView = GMSMapView(frame: .zero, camera: camera)
    self.view = mapView
    mapView.delegate = self
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
  }

}

5. Оформите карту (необязательно)

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

Создать идентификатор карты

Если вы еще не создали идентификатор карты со связанным с ним стилем карты, см. руководство по идентификаторам карт , чтобы выполнить следующие шаги:

  1. Создайте идентификатор карты.
  2. Свяжите идентификатор карты со стилем карты.

Добавьте идентификатор карты в свое приложение

Чтобы использовать идентификатор карты, созданный на предыдущем шаге, откройте файл ViewController.swift и в методе loadView создайте объект GMSMapID , указав ему идентификатор карты. Затем измените экземпляр GMSMapView , передав объект GMSMapID в качестве параметра.

ViewController.swift

  override func loadView() {

    // Load the map at set latitude/longitude and zoom level
    let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 11)
    let mapID = GMSMapID(identifier: "YOUR_MAP_ID")

    mapView = GMSMapView(frame: .zero, mapID: mapID, camera: camera)
    self.view = mapView
    mapView.delegate = self
  }

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

6. Добавьте маркеры на карту

Разработчики используют Maps SDK для iOS для множества задач, но размещение маркеров на карте, безусловно, является самым популярным. Маркеры отмечают определённые точки на карте и являются распространённым элементом пользовательского интерфейса для взаимодействия с пользователем. Если вы когда-либо пользовались Google Картами, то, вероятно, знакомы с маркером по умолчанию, который выглядит как красные булавки на рисунке 2:

Карта с красными маркерами

Рисунок 2. Карта с красными маркерами.

На этом шаге показано, как использовать класс GMSMarker для размещения маркеров на карте.

Обратите внимание, что маркеры нельзя разместить на карте до тех пор, пока карта не будет загружена из предыдущего шага в событии жизненного цикла loadView контроллера представления, поэтому выполните эти шаги в событии жизненного цикла viewDidLoad , которое вызывается после загрузки представления (и карты).

  1. Определите объект CLLocationCoordinate2D .

CLLocationCoordinate2D — это структура, доступная в библиотеке iOS CoreLocation , которая определяет географическое местоположение с заданными широтой и долготой. Чтобы начать создавать свой первый маркер, определите объект CLLocationCoordinate2D и задайте широту и долготу центра карты. Координаты центра карты доступны из представления карты с помощью свойств camera.target.latitude и camera.target.longitude .

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
  1. Создайте экземпляр GMSMarker .

Maps SDK для iOS предоставляет класс GMSMarker . Каждый экземпляр GMSMarker представляет отдельный маркер на карте и создаётся путём вызова метода markerWithPosition: и передачи ему объекта CLLocationCoordinate2D , который указывает SDK, где разместить маркер на карте.

    let marker = GMSMarker(position: mapCenter)
  1. Установите пользовательский значок маркера.

Стандартный красный маркер-булавка в Google Картах — это здорово, но и настройка карты тоже хороша! К счастью, использовать собственный маркер с Maps SDK для iOS очень просто. Обратите внимание, что проект StarterApp включает изображение под названием «custom_pin.png», которое вы можете использовать, но вы можете использовать любое другое изображение.

Чтобы установить пользовательский маркер, задайте для свойства icon маркера экземпляр UIImage .

    marker.icon = UIImage(named: "custom_pin.png")
  1. Отобразить маркер на карте.

Ваш маркер создан, но пока не отображается на карте. Для этого установите свойство map экземпляра GMSMarker на экземпляр GMSMapView .

    marker.map = mapView

Теперь перезагрузите приложение и увидьте свою первую карту с маркером, как показано на рисунке 3!

Приложение iOS с картой Google Maps и красным маркером в центре

Рисунок 3. Приложение iOS с Google Картами и красным маркером в центре.

Итак, в этом разделе вы создали экземпляр класса GMSMarker и применили его к представлению карты для отображения маркера. Обновлённое событие жизненного цикла viewDidLoad в ViewController.swift теперь должно выглядеть следующим образом:

  override func viewDidLoad() {
    super.viewDidLoad()

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
    let marker = GMSMarker(position: mapCenter)

    marker.icon = UIImage(named: "custom_pin.png")
    marker.map = mapView
  }

7. Включить кластеризацию маркеров

Если вы используете много маркеров или маркеры расположены слишком близко друг к другу, вы можете столкнуться с проблемой, когда маркеры перекрываются или кажутся слишком тесными, что негативно сказывается на пользовательском опыте. Например, если два маркера расположены очень близко друг к другу, может возникнуть ситуация, показанная на рисунке 4:

Два маркера очень близко друг к другу

Рисунок 4. Два маркера, расположенные очень близко друг к другу.

Вот тут-то и пригодится кластеризация маркеров. Кластеризация маркеров — еще одна часто реализуемая функция, которая группирует близлежащие маркеры в один значок, который меняется в зависимости от уровня масштабирования, как показано на рисунке 5:

Пример маркеров, объединенных в один значок

Рисунок 5. Пример маркеров, объединенных в один значок.

Алгоритм кластеризации маркеров разбивает видимую область карты на сетку, а затем группирует значки, находящиеся в одной ячейке. Команда платформы Google Карт создала полезную библиотеку с открытым исходным кодом под названием Google Maps SDK for iOS Utility Library, которая, помимо прочего, автоматически выполняет кластеризацию маркеров. Подробнее о кластеризации маркеров читайте в документации платформы Google Карт или ознакомьтесь с исходным кодом библиотеки iOS Utility Library на GitHub .

  1. Добавьте больше маркеров на карту.

Чтобы увидеть кластеризацию маркеров в действии, вам потребуется много маркеров на карте. Для оптимизации процесса используйте генератор маркеров, предоставленный в стартовом проекте MarkerGenerator.swift .

Чтобы добавить на карту заданное количество маркеров, вызовите MarkerGenerator(near:count:).markerArray в жизненном цикле viewDidLoad контроллера представления, расположенном под кодом из предыдущего шага. Этот метод создаёт маркеры в указанном в count в случайных точках вокруг координат, указанных в объекте CLLocationCoordinate2D . В этом случае вы можете передать ему созданную ранее переменную mapCenter . Маркеры возвращаются в объекте [GMSMarker] .

    // Generate many markers
    let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray

Вы можете проверить, как выглядит такое количество маркеров, добавив следующие строки после определения markerArray и запустив приложение. Обязательно закомментируйте эти строки, прежде чем переходить к следующим шагам, где для управления отображением маркеров используется Marker Clusterer:

    // Comment the following code out if using the marker clusterer
    // to manage markers instead.
    for marker in markerArray {
      marker.map = mapView
    }
  1. Импортируйте библиотеку утилит Google Maps SDK для iOS.

Чтобы добавить библиотеку утилиты Maps iOS в качестве зависимости к вашему проекту, добавьте это в список зависимостей в верхней части ViewController.swift :

import GoogleMapsUtils
  1. Настройте кластеризатор маркеров.

Чтобы использовать кластеризатор маркеров, необходимо настроить три параметра: алгоритм кластеризации, генератор значков и рендерер. Алгоритм определяет поведение кластеризации маркеров, например, расстояние между маркерами, включаемыми в один кластер. Генератор значков предоставляет значки кластеров для использования на разных уровнях масштабирования. Рендерер отвечает за рендеринг значков кластеров на карте.

При желании вы можете написать всё это с нуля. Кроме того, библиотека Maps для iOS предоставляет стандартные реализации, ускоряющие процесс. Добавьте следующие строки:

    // Set up the cluster manager with a supplied icon generator and renderer.
    let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
    let iconGenerator = GMUDefaultClusterIconGenerator()
    let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
  1. Создайте экземпляр GMUClusterManager .

GMUClusterManager — это класс, реализующий кластеризацию маркеров с использованием указанного вами алгоритма, генератора значков и рендерера. Чтобы создать рендерер и сделать его доступным для представления карты, сначала добавьте переменную экземпляра в реализацию ViewController для хранения экземпляра менеджера кластера:

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!
}

Затем создайте экземпляр GMUClusterManager в событии жизненного цикла viewDidLoad :

    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
  1. Добавьте маркеры и запустите кластеризатор маркеров.

Теперь, когда экземпляр кластеризатора маркеров настроен, передайте диспетчеру кластера массив маркеров, которые нужно кластеризовать, вызвав add(items:) , а затем запустите кластеризатор, вызвав cluster .

    clusterManager.setMapDelegate(self)
    clusterManager.add(markerArray)
    clusterManager.cluster()

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

Приложение iOS с картой Google и кластеризованными маркерами

Рисунок 6. Приложение iOS с Google Maps и сгруппированными маркерами.

Итак, на этом шаге вы настроили экземпляр кластеризатора маркеров из библиотеки утилит Google Maps SDK для iOS, а затем использовали его для кластеризации 100 маркеров на карте. Событие жизненного цикла viewDidLoad в ViewController.swift теперь должно выглядеть так:

  override func viewDidLoad() {
    super.viewDidLoad()

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
    let marker = GMSMarker(position: mapCenter)

    marker.icon = UIImage(named: "custom_pin.png")
    marker.map = mapView

    // Generate many markers
    let markerArray = MarkerGenerator(near: mapCenter, count: 100).markerArray
    // Comment the following code out if using the marker clusterer
    // to manage markers instead.
    //    for marker in markerArray {
    //      marker.map = mapView
    //    }

    // Set up the cluster manager with a supplied icon generator and renderer.
    let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
    let iconGenerator = GMUDefaultClusterIconGenerator()
    let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)

    clusterManager.setMapDelegate(self)
    clusterManager.add(markerArray)
    clusterManager.cluster()
  }

8. Добавьте взаимодействие с пользователем

Теперь у вас есть отличная карта с маркерами и кластеризацией маркеров. На этом этапе вы добавите дополнительную обработку пользовательских взаимодействий с помощью GMSMapViewDelegate , который вы ранее установили для контроллера представления, чтобы улучшить пользовательский опыт использования вашей карты.

Maps SDK для iOS предоставляет комплексную систему событий, реализованную через делегат вида карты, который включает обработчики событий, позволяющие выполнять код при различных взаимодействиях пользователя. Например, делегат MapView включает методы, позволяющие инициировать выполнение кода при таких взаимодействиях, как нажатие пользователем на карту и маркеры, панорамирование карты, увеличение и уменьшение масштаба и т. д.

На этом этапе вы программно перемещаете карту в центр относительно любого маркера, на который нажимает пользователь.

  1. Реализуйте прослушиватель нажатий маркера.

mapView(_:didTap:) вызывается каждый раз, когда пользователь нажимает на один из маркеров, созданных вами ранее, и каждый раз, когда пользователь нажимает на кластер маркеров (внутренне кластеры маркеров реализованы как экземпляр GMSMarker ).

Чтобы реализовать прослушиватель событий, начните с его добавления заглушки в конец ViewController.swift перед закрывающейся фигурной скобкой.

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    return false
  }

Обратите внимание, что метод возвращает false . Это указывает iOS SDK на необходимость продолжить выполнение стандартного поведения GMSMarker , например, отображать информационное окно , если оно настроено, после выполнения кода обработчика событий.

  1. Обрабатывайте событие нажатия и анимируйте камеру для центрирования карты при нажатии маркера или группы маркеров.

При вызове mapView(_:didTap:) передаёт экземпляр GMSMarker , к которому был прикоснулся пользователь, чтобы вы могли обработать его в своём коде. Вы можете использовать этот экземпляр для центрирования карты, вызвав animate(toLocation:) для представления карты из обработчика событий и передав ему положение экземпляра маркера из свойства position .

    // Animate to the marker
    mapView.animate(toLocation: marker.position)
  1. При нажатии на кластер маркеров увеличьте его масштаб.

Распространенный UX-шаблон — увеличение масштаба кластеров маркеров при нажатии на них. Это позволяет пользователям видеть кластеры маркеров, поскольку кластер увеличивается при уменьшении масштаба.

Как отмечалось ранее, значок кластера маркеров фактически представляет собой реализацию GMSMarker с пользовательским значком. Как же определить, был ли нажат маркер или кластер маркеров? Когда менеджер кластеризации маркеров создаёт новый значок кластера, он реализует экземпляр GMSMarker для соответствия протоколу GMUCluster. Вы можете использовать условие для проверки соответствия маркера, переданного в обработчик событий, этому протоколу.

Как только вы программно определили, что кластер был использован, вы можете вызвать animate(toZoom:) для экземпляра представления карты и установить масштаб, равный текущему уровню масштабирования плюс один. Текущий уровень масштабирования доступен для экземпляра mapView в свойстве camera.zoom .

Также обратите внимание, как следующий код возвращает true . Это сообщает обработчику событий, что обработка события завершена, и не требует дальнейшего выполнения кода в обработчике. Одна из причин этого — предотвратить выполнение базовым объектом GMSMarker оставшейся части его поведения по умолчанию, например, отображения информационного окна, что было бы бессмысленно в случае нажатия на значок кластера.

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

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

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

Ваш метод mapView(_:didTap:) должен выглядеть следующим образом:

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    // Animate to the marker
    mapView.animate(toLocation: marker.position)

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

    return false
  }

9. Нарисуйте на карте

На данный момент вы создали карту Сиднея с маркерами в 100 случайных точках и обрабатывали взаимодействие с пользователем. На последнем этапе этой лабораторной работы вы используете функции рисования Maps SDK для iOS, чтобы добавить дополнительную полезную функцию к вашему опыту работы с картой.

Представьте, что эта карта будет использоваться пользователями, желающими исследовать Сидней. Полезной функцией было бы отображение радиуса вокруг маркера при щелчке по нему. Это позволило бы пользователю быстро понять, какие ещё места находятся в непосредственной близости от выбранного маркера.

iOS SDK включает набор функций для рисования фигур на карте, таких как квадраты, многоугольники, линии и круги. На этом этапе отрисовываем круг, отображающий область радиусом 800 метров (примерно полмили) вокруг маркера при щелчке по нему.

  1. Добавьте переменную экземпляра circle в реализацию ViewController.

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

Для этого обновите реализацию ViewController следующим образом:

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!
  private var circle: GMSCircle? = nil
  ...
}
  1. При нажатии на маркер нарисуйте круг.

В нижней части метода mapView(_:didTap:) прямо над оператором return false добавьте показанный здесь код для создания экземпляра класса GMSCircle из iOS SDK для рисования нового круга радиусом 800 метров путем вызова GMSCircle(position:radius:) и передачи ему позиции нажатого маркера, как вы это делали при центрировании карты.

    // Draw a new circle around the tapped marker
    circle = GMSCircle(position: marker.position, radius: 800)
  1. Оформите круг.

По умолчанию GMSCircle рисует круг с чёрной обводкой и прозрачной заливкой. Этого достаточно для отображения радиуса, но выглядит он не очень хорошо и немного плохо различим. Затем задайте кругу цвет заливки, чтобы улучшить его стилистику, назначив UIColor свойству fillColor круга. Приведённый здесь код добавляет серую заливку с прозрачностью 50%.

    circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
  1. Нарисуйте круг на карте.

Как и при создании маркеров ранее, создание экземпляра GMSCircle не приводит к его отображению на карте. Для этого назначьте экземпляр представления карты свойству map круга.

    circle?.map = mapView
  1. Удалите все ранее нарисованные круги.

Как уже отмечалось, постоянное добавление кругов на карту было бы не очень удобным для пользователя. Чтобы удалить круг, отрисованный предыдущим касанием, установите свойство map circle в nil в верхней части mapView(_:didTap:) .

    // Clear previous circles
    circle?.map = nil

Перезагрузите приложение и коснитесь маркера. При каждом касании маркера должен появиться новый круг, а все ранее отрисованные круги должны быть удалены, как показано на рисунке 7.

Круг, нарисованный вокруг отпечатанного маркера

Рисунок 7. Круг, нарисованный вокруг отпечатанного маркера.

Напомним, что на этом этапе вы использовали класс GMSCircle для визуализации круга при каждом касании маркера.

Метод mapView(_:didTap:) должен выглядеть так:

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {

    // Clear previous circles
    circle?.map = nil

    // Animate to the marker
    mapView.animate(toLocation: marker.position)

    // If the tap was on a marker cluster, zoom in on the cluster
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      return true
    }

    // Draw a new circle around the tapped marker
    circle = GMSCircle(position: marker.position, radius: 800)
    circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
    circle?.map = mapView
    return false
  }

10. Поздравления

Вы успешно создали приложение iOS с интерактивной картой Google.

Что вы узнали

Что дальше?

Какие еще практические занятия вы хотели бы увидеть?

Визуализация данных на картах Подробнее о настройке стиля моих карт Создание 3D-взаимодействий на картах

Не нашли нужную вам практическую работу? Запросите её в новом выпуске здесь .