Dodawanie mapy do aplikacji na iOS (Swift)

1. Zanim zaczniesz

Z tego ćwiczenia w Codelabs dowiesz się, jak zacząć korzystać z Google Maps Platform do tworzenia aplikacji na iOS w języku Swift. Utworzysz aplikację na iOS, która:

  • Wczytuje pakiet Maps SDK na iOS i bibliotekę narzędziową pakietu Maps SDK na iOS.
  • Wyświetla mapę wyśrodkowaną na Sydney w Australii.
  • Wyświetla niestandardowe znaczniki dla 100 punktów w Sydney.
  • Implementuje łączenie znaczników w klastry.
  • Umożliwia interakcję użytkownika, która po kliknięciu znacznika ponownie wyśrodkowuje mapę i rysuje na niej okrąg.

Mapa ze znacznikami w aplikacji na iOS

Wymagania wstępne

  • Podstawowa wiedza na temat języka Swift i tworzenia aplikacji na iOS.

Jakie zadania wykonasz

  • Wczytaj pakiet Maps SDK na iOS i bibliotekę narzędziową Google Maps SDK na iOS.
  • Wczytaj mapę.
  • Używaj znaczników, znaczników niestandardowych i grupowania znaczników.
  • Korzystaj z systemu zdarzeń pakietu Maps SDK na iOS, aby obsługiwać interakcje użytkowników.
  • Sterowanie kamerą mapy za pomocą kodu.
  • Rysuj na mapie.

Czego potrzebujesz

Aby ukończyć to ćwiczenie, potrzebujesz tych kont, usług i narzędzi:

  • Xcode 12.0 lub nowszy z pakietem SDK w wersji 12.0 lub nowszej.
  • Zainstalowano Cocoapods.
  • Konto Google Cloud Platform z włączonymi płatnościami (patrz następny krok).
  • Projekt w konsoli Google Cloud z włączonym pakietem Maps SDK na iOS (patrz następny krok).

2. Konfiguracja

Aby wykonać krok włączenia poniżej, musisz włączyć Maps SDK na iOS.

Konfigurowanie Google Maps Platform

Jeśli nie masz jeszcze konta Google Cloud Platform i projektu z włączonymi płatnościami, zapoznaj się z przewodnikiem Pierwsze kroki z Google Maps Platform, aby utworzyć konto rozliczeniowe i projekt.

  1. W konsoli Google Cloud kliknij menu projektu i wybierz projekt, którego chcesz użyć w tym samouczku.

  1. Włącz interfejsy API i pakiety SDK Google Maps Platform wymagane w tym samouczku w Google Cloud Marketplace. Aby to zrobić, wykonaj czynności opisane w tym filmie lub tej dokumentacji.
  2. Wygeneruj klucz interfejsu API na stronie Dane logowania w konsoli Cloud. Możesz wykonać czynności opisane w tym filmie lub tej dokumentacji. Wszystkie żądania wysyłane do Google Maps Platform wymagają klucza interfejsu API.

Krótkie wprowadzenie

Aby jak najszybciej rozpocząć pracę, przygotowaliśmy kod początkowy, który pomoże Ci w tym samouczku.

  1. Sklonuj repozytorium, jeśli masz zainstalowany program git.
git clone https://github.com/googlemaps/codelab-maps-platform-101-swift.git

Możesz też kliknąć Podaj mi kod, aby pobrać kod źródłowy.

  1. Po pobraniu kodu otwórz projekt StarterApp w katalogu /starter. Ten projekt zawiera podstawową strukturę plików potrzebną do ukończenia ćwiczenia. Wszystko, czego potrzebujesz do pracy, znajduje się w katalogu /starter/StarterApp.

Aby zobaczyć działający pełny kod rozwiązania, wyświetl ukończony kod w katalogu /solution/SolutionApp.

3. Instalowanie pakietu Maps SDK na iOS

Pierwszym krokiem w korzystaniu z pakietu Maps SDK na iOS jest zainstalowanie wymaganych zależności. Ten proces składa się z 2 etapów: zainstalowania pakietu Maps SDK na iOS i biblioteki narzędziowej pakietu Maps SDK na iOS z menedżera zależności Cocoapods oraz podania klucza interfejsu API do pakietu SDK.

  1. Dodaj pakiet Maps SDK na iOS i bibliotekę narzędziową pakietu Maps SDK na iOS do Podfile.

W tym samouczku wykorzystujemy zarówno pakiet Maps SDK na iOS, który zapewnia wszystkie podstawowe funkcje Map Google, jak i bibliotekę narzędziową Maps iOS, która udostępnia różne narzędzia do wzbogacania mapy, w tym grupowanie znaczników.

Aby rozpocząć, otwórz w Xcode (lub w ulubionym edytorze tekstu) plik Podfile i zaktualizuj go, aby zawierał zależności pakietu Maps SDK na iOS i biblioteki narzędziowej pod komentarzem # Pods for StarterApp:

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

Najnowszą wersję pakietu SDK i wskazówki dotyczące jego obsługi znajdziesz w dokumentacji wersji pakietu Maps SDK na iOS.

Twój Podfile powinien wyglądać tak:

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. Zainstaluj pody pakietu Maps SDK na iOS i biblioteki narzędziowej pakietu Maps SDK na iOS.

Aby zainstalować zależności, uruchom polecenie pod install w katalogu /starter z poziomu wiersza poleceń. Cocoapods automatycznie pobiera zależności i tworzy StarterApp.xcworkspace.

  1. Po zainstalowaniu zależności uruchom polecenie open StarterApp.xcworkspace w katalogu /starter, aby otworzyć plik w Xcode, a następnie uruchom aplikację w symulatorze iPhone'a, naciskając Command+R. Jeśli wszystko jest skonfigurowane prawidłowo, symulator uruchomi się i wyświetli czarny ekran. Nie martw się, nic jeszcze nie zostało utworzone, więc to normalne.
  2. Zaimportuj pakiet SDK w AppDelegate.swift.

Po zainstalowaniu zależności musisz podać klucz interfejsu API w pakiecie SDK. Pierwszym krokiem jest zaimportowanie pakietu Maps SDK na iOS jako zależności. W tym celu umieść poniższy kod pod instrukcją import UIKit import:

import GoogleMaps
  1. Przekaż klucz interfejsu API do pakietu SDK na iOS, wywołując provideAPIKeyGMSServicesapplication: 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
  }

Zaktualizowany plik AppDelegate.swift powinien teraz wyglądać tak:

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
  }

}

Zastąp YOUR_API_KEY kluczem interfejsu API utworzonym w konsoli Cloud Console.

Gdy masz już zainstalowane zależności i klucz interfejsu API, możesz zacząć wywoływać pakiet Maps SDK na iOS.

4. Wyświetlanie mapy

Czas wyświetlić pierwszą mapę.

Najczęściej używaną częścią pakietu Maps SDK na iOS jest klasa GMSMapView, która udostępnia wiele metod umożliwiających tworzenie instancji mapy i manipulowanie nimi. Aby to zrobić:

  1. Otwórz pokój ViewController.swift.

W tym miejscu wykonasz pozostałą część ćwiczenia. Zauważ, że zdarzenia cyklu życia loadViewviewDidLoad kontrolera widoku są już dla Ciebie przygotowane.

  1. Zaimportuj pakiet Maps SDK na iOS, dodając ten wiersz na początku pliku:
import GoogleMaps
  1. Zadeklaruj zmienną instancji ViewController, aby przechowywać GMSMapView.

Instancja GMSMapView to główny obiekt, z którym będziesz pracować w tym laboratorium, i będziesz się do niego odwoływać oraz wykonywać na nim działania w różnych metodach cyklu życia kontrolera widoku. Aby udostępnić tę wartość, zaktualizuj implementację ViewController, deklarując zmienną instancji do jej przechowywania:

class ViewController: UIViewController {

  private var mapView: GMSMapView!

  ...
}
  1. loadView utwórz instancję GMSCameraPosition.

GMSCameraPosition określa, gdzie mapa jest wyśrodkowana, i poziom powiększenia, który jest wyświetlany. Ten kod wywołuje metodę cameraWithLatitude:longitude:zoom:, aby wyśrodkować mapę na Sydney w Australii przy szerokości geograficznej –33, 86 i długości geograficznej 151, 20 oraz poziomie powiększenia 12:

let camera:GMSCameraPosition = GMSCameraPosition.camera(withLatitude: -33.86, longitude: 151.20, zoom: 12)
  1. loadView utwórz instancję GMSMapView, aby utworzyć instancję mapy.

Aby utworzyć nową instancję mapy, wywołaj funkcję GMSMapView(frame: CGRect, camera: GMSCameraPosition). Zwróć uwagę, że ramka jest ustawiona na CGRect.zero, czyli zmienną globalną z biblioteki CGGeometry iOS, która określa ramkę o szerokości 0 i wysokości 0, znajdującą się w kontrolerze widoku w pozycji (0,0). Kamera zostanie ustawiona w utworzonej przed chwilą pozycji.

Następnie, aby wyświetlić mapę, ustaw widok główny kontrolera widoku na mapView, co spowoduje wyświetlenie mapy na pełnym ekranie.

    mapView = GMSMapView(frame: .zero, camera: camera)
    self.view = mapView
  1. Ustaw GMSMapViewDelegate na kontroler widoku.

Po wdrożeniu delegat widoku mapy umożliwia obsługę zdarzeń pochodzących z interakcji użytkownika z instancją GMSMapView, co będzie potrzebne później.

Najpierw zaktualizuj interfejs ViewController, aby był zgodny z protokołem GMSMapViewDelegate:

class ViewController: UIViewController, GMSMapViewDelegate

Następnie dodaj ten wiersz w funkcji loadView, aby ustawić GMSMapViewDelegate na ViewController.

    mapView.delegate = self

Teraz ponownie załaduj aplikację w symulatorze iOS (Command+R). Mapa powinna wyglądać tak jak na tym zrzucie ekranu:

Aplikacja na iOS wyświetlająca mapę Google

Ilustracja 1. Aplikacja na iOS wyświetlająca Mapę Google.

Podsumowując, w tym kroku utworzyliśmy instancję GMSMapView, aby wyświetlić mapę wyśrodkowaną na Sydney w Australii.

Plik ViewController.swift powinien teraz wyglądać tak:

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. Nadawanie stylu mapie (opcjonalnie)

Styl mapy możesz dostosować za pomocą definiowania stylów map w Google Cloud.

Tworzenie identyfikatora mapy

Jeśli nie masz jeszcze identyfikatora mapy powiązanego ze stylem mapy, zapoznaj się z przewodnikiem Identyfikatory mapy i wykonaj te czynności:

  1. Utwórz identyfikator mapy.
  2. powiązać identyfikator mapy ze stylem mapy.

Dodawanie identyfikatora mapy do aplikacji

Aby użyć identyfikatora mapy utworzonego w poprzednim kroku, otwórz plik ViewController.swift i w metodzie loadView utwórz obiekt GMSMapID i podaj mu identyfikator mapy. Następnie zmodyfikuj instancję GMSMapView, podając obiekt GMSMapID jako parametr.

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
  }

Gdy to zrobisz, uruchom aplikację, aby zobaczyć mapę w wybranym stylu.

6. Dodawanie znaczników do mapy

Deweloperzy korzystają z pakietu Maps SDK na iOS na wiele sposobów, ale umieszczanie znaczników na mapie jest zdecydowanie najpopularniejsze. Znaczniki wskazują konkretne punkty na mapie i są powszechnym elementem interfejsu do obsługi interakcji użytkownika. Jeśli korzystasz już z Map Google, prawdopodobnie znasz domyślny znacznik, który wygląda jak czerwone pinezki na ilustracji 2:

Mapa z czerwonymi znacznikami

Rysunek 2. Mapa z czerwonymi znacznikami.

Ten krok pokazuje, jak użyć klasy GMSMarker, aby umieścić znaczniki na mapie.

Pamiętaj, że markerów nie można umieszczać na mapie, dopóki nie zostanie ona wczytana z poprzedniego kroku w zdarzeniu cyklu życia loadView kontrolera widoku. Wykonaj te czynności w zdarzeniu cyklu życia viewDidLoad, które jest wywoływane po wczytaniu widoku (i mapy).

  1. Określ obiekt CLLocationCoordinate2D.

CLLocationCoordinate2D to struktura udostępniana przez bibliotekę CoreLocation w iOS, która określa lokalizację geograficzną na podstawie szerokości i długości geograficznej. Aby rozpocząć tworzenie pierwszego markera, zdefiniuj obiekt CLLocationCoordinate2D i ustaw szerokość i długość geograficzną na środek mapy. Współrzędne środka mapy są dostępne w widoku mapy za pomocą właściwości camera.target.latitudecamera.target.longitude.

    // Add a single marker with a custom icon
    let mapCenter = CLLocationCoordinate2DMake(mapView.camera.target.latitude, mapView.camera.target.longitude)
  1. Utwórz instancję GMSMarker.

Pakiet Maps SDK na iOS udostępnia klasę GMSMarker. Każda instancja GMSMarker reprezentuje pojedynczy znacznik na mapie i jest tworzona przez wywołanie funkcji markerWithPosition: oraz przekazanie jej obiektu CLLocationCoordinate2D, aby poinformować pakiet SDK, gdzie umieścić znacznik na mapie.

    let marker = GMSMarker(position: mapCenter)
  1. Ustaw niestandardową ikonę markera.

Domyślny czerwony znacznik w Mapach Google jest świetny, ale dostosowywanie mapy też jest fajne. Na szczęście używanie niestandardowego znacznika jest proste dzięki pakietowi Maps SDK na iOS. Zauważ, że projekt StarterApp zawiera obraz o nazwie „custom_pin.png”, którego możesz użyć, ale możesz też użyć dowolnego innego obrazu.

Aby ustawić niestandardowy znacznik, ustaw właściwość icon znacznika na instancję UIImage.

    marker.icon = UIImage(named: "custom_pin.png")
  1. Wyświetl znacznik na mapie.

Znacznik zostanie utworzony, ale nie będzie jeszcze widoczny na mapie. Aby to zrobić, ustaw właściwość map instancji GMSMarker na instancję GMSMapView.

    marker.map = mapView

Teraz ponownie załaduj aplikację i zobacz swoją pierwszą mapę ze znacznikiem, tak jak na rysunku 3.

Aplikacja na iOS z Mapą Google i czerwonym znacznikiem pośrodku

Ilustracja 3. Aplikacja na iOS z Mapami Google i czerwonym znacznikiem na środku.

Podsumowując, w tej sekcji utworzyliśmy instancję klasy GMSMarker i zastosowaliśmy ją do widoku mapy, aby wyświetlić na niej znacznik. Zaktualizowane zdarzenie cyklu życia viewDidLoad w ViewController.swift powinno teraz wyglądać tak:

  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. Włączanie klastrowania znaczników

Jeśli używasz wielu znaczników lub są one blisko siebie, mogą się nakładać lub być zbyt blisko siebie, co pogarsza komfort użytkownika. Jeśli np. 2 markery znajdują się bardzo blisko siebie, może to wyglądać tak jak na rysunku 4:

Dwa markery bardzo blisko siebie

Rysunek 4. Dwa markery znajdujące się bardzo blisko siebie.

W takiej sytuacji przydaje się grupowanie znaczników. Kolejną często stosowaną funkcją jest grupowanie znaczników, które łączy pobliskie znaczniki w jedną ikonę zmieniającą się w zależności od poziomu powiększenia, jak pokazano na rysunku 5:

Przykład znaczników zgrupowanych w jedną ikonę

Rysunek 5. Przykład znaczników zgrupowanych w jedną ikonę.

Algorytm klastrowania znaczników dzieli widoczny obszar mapy na siatkę, a następnie grupuje ikony znajdujące się w tej samej komórce. Zespół Google Maps Platform stworzył przydatną bibliotekę narzędziową o otwartym kodzie źródłowym o nazwie Google Maps SDK for iOS Utility Library, która m.in. automatycznie obsługuje grupowanie znaczników. Więcej informacji o grupowaniu znaczników znajdziesz w dokumentacji Google Maps Platform. Możesz też sprawdzić źródło biblioteki narzędziowej iOS na GitHub.

  1. Dodaj do mapy więcej znaczników.

Aby zobaczyć działanie klastrowania znaczników, musisz mieć na mapie wiele znaczników. Aby to uprościć, użyj generatora znaczników dostępnego w projekcie początkowym w MarkerGenerator.swift.

Aby dodać do mapy określoną liczbę znaczników, wywołaj funkcję MarkerGenerator(near:count:).markerArray w metodzie viewDidLoad kontrolera widoku poniżej kodu z poprzedniego kroku. Metoda tworzy liczbę markerów określoną w parametrze count w losowych lokalizacjach wokół współrzędnych podanych w obiekcie CLLocationCoordinate2D. W takim przypadku możesz przekazać do niego utworzoną wcześniej zmienną mapCenter. Markery są zwracane w obiekcie [GMSMarker].

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

Możesz sprawdzić, jak wygląda taka liczba znaczników, dodając te wiersze po definicji markerArray, a następnie uruchamiając aplikację. Przed przejściem do kolejnych kroków, w których do zarządzania wyświetlaniem znaczników używany jest moduł Marker Clusterer, pamiętaj, aby zakomentować te wiersze:

    // Comment the following code out if using the marker clusterer
    // to manage markers instead.
    for marker in markerArray {
      marker.map = mapView
    }
  1. Zaimportuj bibliotekę narzędziową pakietu Google Maps SDK na iOS.

Aby dodać bibliotekę narzędziową Map Google na iOS jako zależność do projektu, dodaj ten kod do listy zależności u góry pliku ViewController.swift:

import GoogleMapsUtils
  1. Skonfiguruj klaster znaczników.

Aby użyć klastrowania znaczników, musisz podać 3 elementy, które określają sposób jego działania: algorytm klastrowania, generator ikon i renderowanie. Algorytm określa sposób grupowania znaczników, np. odległość między znacznikami, które mają być uwzględnione w tym samym klastrze. Generator ikon udostępnia ikony klastrów, które mają być używane na różnych poziomach powiększenia. Moduł renderujący odpowiada za renderowanie ikon klastrów na mapie.

Jeśli wolisz, możesz je wszystkie napisać od zera. Biblioteka narzędziowa Map na iOS udostępnia domyślne implementacje, które przyspieszają ten proces. Dodaj te wiersze:

    // 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. Utwórz instancję GMUClusterManager.

GMUClusterManager to klasa, która implementuje grupowanie znaczników przy użyciu określonego przez Ciebie algorytmu, generatora ikon i renderera. Aby utworzyć moduł renderujący i udostępnić go widokowi mapy, najpierw dodaj zmienną instancji do implementacji ViewController, aby przechowywać instancję menedżera klastrów:

class ViewController: UIViewController, GMSMapViewDelegate {

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

Następnie utwórz instancję GMUClusterManager w zdarzeniu cyklu życia viewDidLoad:

    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
  1. Dodaj znaczniki i uruchom narzędzie do klastrowania znaczników.

Po skonfigurowaniu instancji klastrowania znaczników przekaż do menedżera klastrów tablicę znaczników do klastrowania, wywołując add(items:), a następnie uruchom klastrowanie, wywołując cluster.

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

Ponownie załaduj aplikację. Powinno się w niej teraz wyświetlać wiele znaczników zgrupowanych w sposób podobny do tego na ilustracji 6. Wypróbuj różne poziomy powiększenia, zsuwając i rozsuwając palce na mapie, aby zobaczyć, jak klastry znaczników dostosowują się do powiększania i pomniejszania.

Aplikacja na iOS z Mapą Google i zgrupowanymi znacznikami

Rysunek 6. Aplikacja na iOS z Mapami Google i zgrupowanymi znacznikami.

Podsumowując, w tym kroku skonfigurowaliśmy instancję narzędzia do klastrowania znaczników z biblioteki narzędziowej pakietu Google Maps SDK na iOS, a następnie użyliśmy jej do klastrowania 100 znaczników na mapie. viewDidLoadZdarzenie związane z cyklem życia w ViewController.swift powinno teraz wyglądać tak:

  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. Dodawanie interakcji użytkownika

Masz teraz świetnie wyglądającą mapę, która wyświetla znaczniki i korzysta z grupowania znaczników. W tym kroku dodasz dodatkową obsługę interakcji użytkownika za pomocą zmiennej GMSMapViewDelegate, którą wcześniej ustawiono na kontroler widoku, aby poprawić wygodę korzystania z mapy.

Pakiet Maps SDK na iOS udostępnia kompleksowy system zdarzeń, który jest implementowany za pomocą delegata widoku mapy. Zawiera on obsługę zdarzeń, która umożliwia wykonywanie kodu, gdy zachodzą różne interakcje użytkownika. Na przykład delegat MapView zawiera metody, które umożliwiają wywoływanie kodu w przypadku interakcji, takich jak kliknięcie mapy i znaczników przez użytkownika, przesuwanie widoku mapy, powiększanie i pomniejszanie oraz inne.

W tym kroku programowo przesuwasz mapę, aby wyśrodkować dowolny znacznik, który kliknie użytkownik.

  1. Zaimplementuj odbiornik kliknięć markera.

mapView(_:didTap:) jest wywoływana za każdym razem, gdy użytkownik kliknie jeden z utworzonych wcześniej znaczników, oraz za każdym razem, gdy kliknie klaster znaczników (wewnętrznie klastry znaczników są implementowane jako instancja GMSMarker).

Aby zaimplementować odbiornik zdarzeń, zacznij od jego utworzenia u dołu pliku ViewController.swift przed zamykającym nawiasem klamrowym.

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

    return false
  }

Zwróć uwagę, że metoda zwraca wartość false. Dzięki temu pakiet SDK na iOS będzie nadal wykonywać domyślne działanie GMSMarker, np. po wykonaniu kodu obsługi zdarzeń wyświetlać okno informacyjne, jeśli jest ono skonfigurowane.

  1. Obsłuż zdarzenie kliknięcia i animuj kamerę, aby wyśrodkować mapę po kliknięciu znacznika lub klastra znaczników.

Gdy wywoływana jest funkcja mapView(_:didTap:), przekazuje ona instancję elementu GMSMarker, który został kliknięty, dzięki czemu możesz obsłużyć ją w kodzie. Możesz użyć tej instancji, aby wyśrodkować mapę, wywołując animate(toLocation:) w widoku mapy z poziomu procedury obsługi zdarzeń i przekazując jej pozycję instancji znacznika z właściwości position.

    // Animate to the marker
    mapView.animate(toLocation: marker.position)
  1. Powiększanie klastra znaczników po jego dotknięciu.

Częstym wzorcem UX jest powiększanie klastrów znaczników po kliknięciu. Dzięki temu użytkownicy mogą wyświetlać zgrupowane markery, ponieważ klaster rozszerza się przy mniejszych poziomach powiększenia.

Jak wspomnieliśmy wcześniej, ikona klastra znaczników to w rzeczywistości implementacja GMSMarker z niestandardową ikoną. Jak więc sprawdzić, czy kliknięto znacznik czy klaster znaczników? Gdy menedżer klastrowania znaczników tworzy nową ikonę klastra, implementuje instancję GMSMarker, aby była zgodna z protokołem o nazwie GMUCluster.. Możesz użyć warunku, aby sprawdzić, czy znacznik przekazany do funkcji obsługi zdarzeń jest zgodny z tym protokołem.

Gdy programowo wykryjesz, że kliknięto klaster, możesz wywołać metodę animate(toZoom:) w instancji widoku mapy i ustawić poziom powiększenia na bieżący poziom powiększenia plus jeden. Bieżący poziom powiększenia jest dostępny w instancji mapView we właściwości camera.zoom.

Zwróć też uwagę, jak poniższy kod zwraca wartość true. Informuje to moduł obsługi zdarzeń, że obsługa zdarzenia została zakończona i nie należy wykonywać w nim żadnego dalszego kodu. Jednym z powodów jest zapobieganie wykonywaniu przez obiekt bazowy GMSMarker pozostałych domyślnych działań, takich jak wyświetlanie okna informacyjnego, co nie miałoby większego sensu w przypadku kliknięcia ikony klastra.

    // 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
    }

Teraz ponownie załaduj aplikację i kliknij kilka znaczników i klastrów znaczników. Gdy dotkniesz jednego z nich, mapa zostanie wyśrodkowana na tym elemencie. Gdy klikniesz klaster znaczników, mapa powiększy się o 1 poziom, a klaster znaczników rozwinie się, aby wyświetlić zgrupowane pod nim znaczniki.

Podsumowując, w tym kroku zaimplementowaliśmy detektor kliknięć znacznika i obsłużyliśmy zdarzenie, aby wyśrodkować widok na klikniętym elemencie i powiększyć go, jeśli jest to ikona klastra znaczników.

Metoda mapView(_:didTap:) powinna wyglądać tak:

  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. Rysowanie na mapie

Do tej pory utworzyliśmy mapę Sydney, na której znajduje się 100 losowych znaczników i która obsługuje interakcje użytkownika. W ostatnim kroku tego laboratorium kodowania użyjesz funkcji rysowania pakietu Maps SDK na iOS, aby dodać do mapy przydatną funkcję.

Wyobraź sobie, że z tej mapy będą korzystać użytkownicy, którzy chcą zwiedzić Sydney. Przydatną funkcją byłoby wizualizowanie promienia wokół znacznika po jego kliknięciu. Dzięki temu użytkownik może szybko sprawdzić, jakie inne miejsca docelowe znajdują się w pobliżu klikniętego znacznika.

Pakiet SDK na iOS zawiera zestaw funkcji do rysowania na mapie kształtów, takich jak kwadraty, wielokąty, linie i okręgi. W tym kroku wyrenderujesz okrąg, aby po kliknięciu znacznika wyświetlić promień 800 metrów (około pół mili).

  1. Dodaj zmienną instancji circle do implementacji elementu ViewController.

Ta zmienna instancji służy do zapisywania ostatnio narysowanego okręgu, aby można go było usunąć przed narysowaniem kolejnego. W końcu nie byłoby to zbyt pomocne dla użytkownika i nie wyglądałoby dobrze, gdyby każdy kliknięty znacznik miał narysowane wokół niego kółko.

Aby to zrobić, zaktualizuj implementację ViewController w ten sposób:

class ViewController: UIViewController, GMSMapViewDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!
  private var circle: GMSCircle? = nil
  ...
}
  1. Narysuj okrąg po kliknięciu znacznika.

U dołu metody mapView(_:didTap:), tuż nad instrukcją return false, dodaj pokazany tu kod, aby utworzyć instancję klasy GMSCircle pakietu SDK na iOS, która narysuje nowe koło o promieniu 800 metrów. W tym celu wywołaj metodę GMSCircle(position:radius:) i przekaż jej pozycję klikniętego znacznika, tak jak podczas ponownego wyśrodkowywania mapy.

    // Draw a new circle around the tapped marker
    circle = GMSCircle(position: marker.position, radius: 800)
  1. Dostosuj styl okręgu.

Domyślnie tag GMSCircle rysuje okrąg z czarną kreską i przezroczystym wypełnieniem. To działa w przypadku wyświetlania promienia, ale nie wygląda zbyt dobrze i jest trochę trudne do zobaczenia. Następnie nadaj okręgowi kolor wypełnienia, aby poprawić styl, przypisując UIColor do właściwości fillColor okręgu. Kod widoczny poniżej dodaje szare wypełnienie z 50-procentową przezroczystością:

    circle?.fillColor = UIColor(red: 0.67, green: 0.67, blue: 0.67, alpha: 0.5)
  1. Wyświetl okrąg na mapie.

Podobnie jak w przypadku tworzenia znaczników, utworzenie instancji GMSCircle nie powoduje, że pojawi się ona na mapie. Aby to zrobić, przypisz instancję widoku mapy do właściwości map okręgu.

    circle?.map = mapView
  1. Usuń wszystkie wcześniej wyrenderowane okręgi.

Jak wspomnieliśmy wcześniej, ciągłe dodawanie okręgów do mapy nie byłoby zbyt wygodne dla użytkowników. Aby usunąć okrąg wyrenderowany przez poprzednie zdarzenie kliknięcia, ustaw właściwość map elementu circle na nil u góry elementu mapView(_:didTap:).

    // Clear previous circles
    circle?.map = nil

Załaduj ponownie aplikację i kliknij znacznik. Po kliknięciu markera powinien pojawić się nowy okrąg, a wcześniej wyrenderowany okrąg powinien zostać usunięty (jak pokazano na rysunku 7).

Kółko narysowane wokół klikniętego znacznika

Rysunek 7. Okrąg narysowany wokół klikniętego znacznika.

Podsumowując, w tym kroku użyliśmy klasy GMSCircle, aby renderować okrąg za każdym razem, gdy klikniesz znacznik.

Metoda mapView(_:didTap:) powinna wyglądać tak:

  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. Gratulacje

Udało Ci się utworzyć aplikację na iOS z interaktywną mapą Google.

Czego się dowiedziałeś

Co dalej?

  • Aby znaleźć więcej inspiracji, przejrzyj lub utwórz rozwidlenie maps-sdk-for-ios-samples repozytorium GitHub z przykładami i wersjami demonstracyjnymi.
  • Skorzystaj z większej liczby ćwiczeń z programowania w Swift, aby tworzyć aplikacje na iOS za pomocą Google Maps Platform
  • Pomóż nam tworzyć treści, które będą dla Ciebie najbardziej przydatne, i wypełnij poniższą ankietę:

Jakie inne codelaby chcesz zobaczyć?

Wizualizacja danych na mapach Więcej informacji o dostosowywaniu stylu map Tworzenie interakcji 3D na mapach

Nie możesz znaleźć warsztatów, które Cię najbardziej interesują? Zgłoś problem tutaj