Agrega un mapa a tu app para iOS (Objective-C)

1. Antes de comenzar

Resumen

En este codelab, aprenderás todo lo que necesitas a fin de comenzar a usar Google Maps Platform con el objetivo de crear apps para iOS en Objective-C. Aprenderás todos los conceptos básicos, desde cómo hacer la configuración hasta cómo cargar el SDK de Maps para iOS, cómo mostrar tu primer mapa, cómo trabajar con marcadores y agruparlos en clústeres, cómo dibujar sobre el mapa y cómo controlar la interacción con el usuario.

Qué crearás

342520482a888519.png

En este codelab, crearás una app para iOS que hace lo siguiente:

  • Carga el SDK de Maps para iOS y la Biblioteca de utilidades del SDK de Maps para iOS.
  • Muestra un mapa centrado en Sídney, Australia.
  • Muestra marcadores personalizados de 100 puntos alrededor de Sídney.
  • Implementa el agrupamiento de marcadores en clústeres.
  • Habilita la interacción del usuario a fin de que, cuando se hace clic en un marcador, se dibuje un círculo sobre el mapa y este vuelva a centrarse.

Qué aprenderás

  • Cómo comenzar a utilizar Google Maps Platform
  • Cómo cargar el SDK de Maps para iOS y la Biblioteca de utilidades del SDK de Google Maps para iOS
  • Cómo cargar un mapa
  • Cómo usar marcadores, marcadores personalizados y agrupamiento de marcadores en clústeres
  • Cómo trabajar con el sistema de eventos del SDK de Maps para iOS a fin de permitir la interacción del usuario
  • Cómo controlar el mapa de forma programática
  • Cómo dibujar sobre el mapa

Requisitos previos

Deberás familiarizarte con los siguientes elementos para completar este codelab. Si ya sabes cómo trabajar con Google Maps Platform, pasa directamente al codelab.

Productos obligatorios de Google Maps Platform

En este codelab, usarás los siguientes productos de Google Maps Platform:

  • SDK de Maps para iOS
  • Biblioteca de utilidades del SDK de Google Maps para iOS

Cómo comenzar a utilizar Google Maps Platform

Si nunca usaste Google Maps Platform, sigue la guía Cómo comenzar a utilizar Google Maps Platform o mira la lista de reproducción Cómo comenzar a utilizar Google Maps Platform para completar los siguientes pasos:

  1. Crear una cuenta de facturación
  2. Crear un proyecto
  3. Habilitar las API y los SDK de Google Maps Platform (enumerados en la sección anterior)
  4. Generar una clave de API

Otros requisitos de este codelab

Para completar este codelab, necesitarás las siguientes cuentas, servicios y herramientas:

  • Una cuenta de Google Cloud Platform con facturación habilitada
  • Una clave de API de Google Maps Platform con el SDK de Maps para iOS habilitado
  • Conocimientos básicos de Objective-C
  • Xcode 12.0 con un SDK objetivo de 12.0 o posterior

2. Prepárate

Para este paso, debes habilitar el SDK de Maps para iOS.

Configura Google Maps Platform

Si todavía no tienes una cuenta de Google Cloud Platform y un proyecto con la facturación habilitada, consulta la guía Cómo comenzar a utilizar Google Maps Platform para crear una cuenta de facturación y un proyecto.

  1. En Cloud Console, haz clic en el menú desplegable del proyecto y selecciona el proyecto que deseas usar para este codelab.

  1. Habilita las API y los SDK de Google Maps Platform necesarios para este codelab en Google Cloud Marketplace. Para hacerlo, sigue los pasos que se indican en este video o esta documentación.
  2. Genera una clave de API en la página Credenciales de Cloud Console. Puedes seguir los pasos que se indican en este video o esta documentación. Todas las solicitudes a Google Maps Platform requieren una clave de API.

Configuración de la plantilla de proyecto inicial

Antes de comenzar este codelab, haz lo siguiente para descargar la plantilla de proyecto inicial y el código completo de la solución:

  1. Descarga o bifurca el repositorio de GitHub correspondiente a este codelab, que puedes encontrar en https://github.com/googlecodelabs/maps-platform-101-objc.

El proyecto inicial, llamado StarterApp, se encuentra en el directorio /starter y tiene la estructura de archivos básica que utilizarás para completar el codelab. Todo lo que necesitas para este proyecto se encuentra en el directorio /starter/StarterApp.

Si deseas ver el código completo de la solución en ejecución, puedes completar los pasos de configuración detallados arriba y consultar la solución en el directorio /solution/SolutionApp.

3. Instala el SDK de Maps para iOS

El primer paso para usar el SDK de Maps para iOS es instalar las dependencias necesarias. Este proceso consta de dos pasos. El primero es instalar el SDK de Maps para iOS y la Biblioteca de utilidades del SDK de Maps para iOS desde el administrador de dependencias de Cocoapods. El segundo es proporcionar tu clave de API al SDK.

  1. Agrega el SDK de Maps para iOS y la Biblioteca de utilidades del SDK de Maps para iOS a Podfile.

En este codelab, usarás el SDK de Maps para iOS, que proporciona todas las funciones principales de Google Maps, y la Biblioteca de utilidades de Maps para iOS, que incluye una variedad de utilidades para enriquecer el mapa, incluido el agrupamiento de marcadores en clústeres.

Para comenzar, en Xcode (o tu editor de texto preferido) abre Pods > Podfile y actualiza el archivo a fin de incluir las dependencias del SDK de Maps para iOS y la Biblioteca de utilidades relacionada en use_frameworks!:

pod 'GoogleMaps'
pod 'Google-Maps-iOS-Utils'
  1. Instala los pods del SDK de Maps para iOS y la Biblioteca de utilidades de Maps para iOS.

A fin de instalar las dependencias, ejecuta pod install en el directorio /starter desde la línea de comandos. CocoaPods descargará las dependencias automáticamente y creará StarterApp.xcworkspace. 3. Una vez que hayas instalado tus dependencias, abre StarterApp.xcworkspace en Xcode y presiona Command+R para ejecutar la app en el simulador de iPhone. Si todo está configurado correctamente, el simulador se iniciará y mostrará una pantalla negra. No te preocupes, está bien que así sea porque todavía no creaste ningún contenido. 4. Importa el SDK en AppDelegate.h.

Ahora que tus dependencias están instaladas, es momento de proporcionar tu clave de API al SDK. Primero, a fin de importar el SDK de Maps para iOS como una dependencia, coloca lo siguiente debajo de la sentencia de importación #import "AppDelegate.h":

@import GoogleMaps;
  1. Luego, debajo de la sentencia de importación del SDK para iOS, declara una constante NSString a la que le asignas el valor de tu clave de API:
static NSString *const kMapsAPIKey = @"YOUR API KEY";
  1. A fin de pasar la clave de API al SDK para iOS, llama a provideAPIKey en GMSServices dentro de application: didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:kMapsAPIKey];
  return YES;
}

El archivo AppDelegate.m actualizado ahora debería verse de la siguiente manera:

#import "AppDelegate.h"
@import GoogleMaps;

static NSString *const kMapsAPIKey = @"YOUR API KEY";

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GMSServices provideAPIKey:kMapsAPIKey];
  return YES;
}
@end

Tu Podfile debería tener el siguiente contenido:

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

target 'StarterApp' do
  use_frameworks!

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

end

Ahora que tus dependencias están instaladas y proporcionaste tu clave de API, ya puedes comenzar a realizar llamadas al SDK de Maps para iOS.

4. Muestra un mapa

Es hora de mostrar tu primer mapa.

La parte más utilizada del SDK de Maps para iOS es la clase GMSMapView, que proporciona muchos de los métodos que te permiten crear y manipular instancias de mapas. A continuación, te indicamos cómo hacerlo.

  1. Abre ViewController.m.

Aquí es donde harás todo el resto del trabajo para este codelab. Notarás que los eventos de ciclo de vida de loadView y viewDidLoad para el controlador de vista ya están incluidos como stubs. 2. Agrega lo siguiente en la parte superior del archivo para importar el SDK de Maps para iOS:

@import GoogleMaps;
  1. Declara una variable de instancia en ViewController para almacenar GMSMapView.

La instancia de GMSMapView es el objeto principal con el que trabajarás en todo este codelab. Harás referencia a él y realizarás acciones que lo afectan desde diferentes métodos del ciclo de vida del controlador de vista. Para que esté disponible, actualiza la implementación de ViewController a fin de declarar una variable de instancia en la cual almacenarlo:

@implementation ViewController {
  GMSMapView *_mapView;
}
  1. En loadView, crea una instancia de GMSCameraPosition.

GMSCameraPosition define el lugar en el que se centrará el mapa y el nivel de zoom con el que se mostrará. Este código llama al método cameraWithLatitude:longitude:zoom: para centrar el mapa en Sídney, Australia, en una latitud de -33.86 y una longitud de 151.20, con un nivel de zoom de 12:

GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
  1. En loadView, genera una instancia de GMSMapView a fin de crear una instancia del mapa.

Llama a mapWithFrame:camera: para crear esa instancia de mapa. Observa cómo el marco se establece en CGRectZero, que es una variable global de la biblioteca CGGeometry de iOS que especifica un marco con ancho y altura iguales a 0, ubicado en la posición (0,0) dentro del controlador de vista. La cámara toma la posición que le acabas de establecer.

Para ver el mapa, establece la vista raíz del controlador de vista en _mapview, lo cual hará que se muestre en pantalla completa.

_mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
self.view = _mapView;
  1. Configura GMSMapViewDelegate en el controlador de vista.

Una vez implementado, el delegado de la vista de mapa te permite controlar eventos de las interacciones de usuarios en la instancia de GMSMapView, los cuales necesitarás en pasos posteriores.

Primero, actualiza la interfaz de ViewController a fin de cumplir con el protocolo para GMSMapViewDelegate:

@interface ViewController ()<GMSMapViewDelegate>

A continuación, agrega lo siguiente para establecer GMSMapViewDelegate en ViewController.

_mapView.delegate = self;

Ahora vuelve a cargar la app en el simulador de iOS (Command+R); se debería mostrar el mapa.

2e6ebac422323aa6.png

En resumen, en este paso creaste una instancia de GMSMapView para mostrar un mapa centrado en la ciudad de Sídney, Australia.

Tu archivo ViewController.m ahora debería verse de la siguiente manera:

#import "ViewController.h"
#import "LocationGenerator.h"
@import GoogleMaps;

@interface ViewController ()<GMSMapViewDelegate>
@end

@implementation ViewController {
  GMSMapView *_mapView;
}

- (void)loadView {
  [super loadView];
  GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86 longitude:151.20 zoom:12];
  _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
  self.view = _mapView;
  _mapView.delegate = self;
}

5. Diseño de mapas basado en Cloud (opcional)

Puedes personalizar el estilo de tu mapa con el diseño de mapas basado en Cloud.

Crea un ID de mapa

Si todavía no creaste un ID de mapa con un estilo de mapa asociado, consulta la guía sobre ID de mapa para completar los siguientes pasos:

  1. Crear un ID de mapa
  2. Asociar un ID de mapa a un estilo de mapa

Cómo agregar el ID de mapa a tu app

Para usar el ID de mapa que creaste en el paso anterior, abre el archivo ViewController.m y, dentro del método loadView, crea un objeto GMSMapID y proporciónale el ID de mapa. Luego, modifica la instancia GMSMapView proporcionando el objeto GMSMapID como parámetro.

ViewController.m

- (void)loadView {
    GMSMapID *mapID = [[GMSMapID alloc] initWithIdentifier:@"YOUR_MAP_ID"];
    _mapView = [GMSMapView mapWithFrame:CGRectZero mapID:mapID camera:camera];
    // ...
}

Una vez que completes esto, ejecuta la app para ver tu mapa con el estilo que seleccionaste.

6. Agrega marcadores al mapa

Hay muchas acciones que los desarrolladores realizan con el SDK de Maps para iOS, pero colocar marcadores en el mapa es definitivamente la más popular. Los marcadores te permiten mostrar puntos específicos en el mapa y son elementos de la IU comunes para controlar la interacción del usuario. Si ya usaste Google Maps, es probable que conozcas el marcador predeterminado, que es el que se ve en la imagen siguiente:

590815267846f166.png

En este paso, aprenderás a usar la clase GMSMarker para colocar marcadores en el mapa.

Ten en cuenta que los marcadores solo se pueden colocar en el mapa una vez que este se haya cargado en el paso anterior, en el evento de ciclo de vida loadView del controlador de vista. Por eso, completarás estos pasos en el evento de ciclo de vida viewDidLoad, al que se llama después de que se cargaron la vista y el mapa.

  1. Define un objeto CLLocationCoordinate2D.

CLLocationCoordinate2D es una estructura que está disponible mediante la biblioteca CoreLocation de iOS, la cual define una ubicación geográfica a partir de la latitud y longitud que se establezcan. Para comenzar a crear tu primer marcador, define un objeto CLLocationCoordinate2D y establece la latitud y longitud en el centro del mapa. Puedes utilizar las propiedades camera.target.latitude y camera.target.longitude para acceder a las coordenadas del centro del mapa desde la vista de mapa.

CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
  1. Crea una instancia de GMSMarker.

El SDK de Maps para iOS proporciona la clase GMSMarker. Cada instancia de GMSMarker representa un marcador individual en el mapa. Para crear este marcador, se llama a markerWithPosition: y se le pasa un objeto CLLocationCoordinate2D para indicarle al SDK dónde colocarlo en el mapa.

GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  1. Establece un ícono de marcador personalizado.

El marcador con forma de pin de color rojo predeterminado de Google Maps es genial, pero también lo es un mapa personalizado. Afortunadamente, es muy sencillo usar marcadores personalizados con el SDK de Maps para iOS. El proyecto StarterApp incluye una imagen llamada "custom_pin.png". Puedes usar esa imagen o cualquiera que desees.

Para establecer el marcador personalizado, configura la propiedad icon del marcador en una instancia de UIImage.

marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  1. Renderiza el marcador en el mapa.

Se creó tu marcador, pero notarás que no está en el mapa. Para ello, configura la propiedad map de la instancia de GMSMarker en una instancia de GMSMapView.

marker.map = _mapView;

Ahora, vuelve a cargar la app y verás tu primer mapa con un marcador.

a4ea8724f8c5ba20.png

En resumen, en esta sección creaste una instancia de la clase GMSMarker y la aplicaste a la vista de mapa para mostrar un marcador. El evento de ciclo de vida actualizado viewDidLoad en ViewController.m debería verse de la siguiente manera:

- (void)viewDidLoad {
  [super viewDidLoad];

  CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude, _mapView.camera.target.longitude);
  GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  marker.map = _mapView;
}

7. Habilita el agrupamiento de marcadores en clústeres

Si usas muchos marcadores o marcadores que están muy cerca entre sí, puedes encontrarte con el problema de que se superpongan o se vean demasiado juntos, lo que generará una mala experiencia del usuario. Por ejemplo, si hay dos marcadores que están muy cerca, podrías tener una situación como la siguiente:

6e39736160c6bce4.png

Para casos como este resulta útil el agrupamiento de marcadores en clústeres. Es una función que se utiliza comúnmente a fin de agrupar los marcadores cercanos en un mismo ícono que cambia según el nivel de zoom de la siguiente manera:

4abb38cd97cab3f1.png

El algoritmo utilizado para el agrupamiento de marcadores en clústeres divide el área visible del mapa en una cuadrícula y, luego, agrupa los íconos que se encuentran en la misma celda. Afortunadamente, no tienes que preocuparte por eso porque el equipo de Google Maps Platform creó una herramienta de código abierto muy útil llamada Biblioteca de utilidades del SDK de Google Maps para iOS. Esta biblioteca, entre muchas otras cosas, administra automáticamente el agrupamiento de marcadores en clústeres por ti. Puedes obtener más información sobre el agrupamiento de marcadores en clústeres en la documentación de Google Maps Platform. También puedes consultar el código fuente de la Biblioteca de utilidades para iOS en GitHub.

  1. Agrega muchos más marcadores al mapa.

Para ver el agrupamiento de marcadores en clústeres en la práctica, tu mapa tiene que tener muchos. A fin de facilitar este proceso, el proyecto inicial incluye un conveniente generador de marcadores en LocationGenerator.m.

Para agregar tantos marcadores a tu mapa como desees, simplemente llama a generateMarkersNear:count: en el ciclo de vida de viewDidLoad del controlador de vista debajo del código del paso anterior. Este método crea la cantidad de marcadores especificados en count en ubicaciones aleatorias alrededor de las coordenadas especificadas en un objeto CLLocationCoordinate2D. En este caso, simplemente puedes pasarle la variable mapCenter que creaste antes. Los marcadores se devuelven en un NSArray.

NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];
  1. Importa la Biblioteca de utilidades del SDK de Google Maps para iOS.

Para agregar la biblioteca de utilidades de Maps para iOS como dependencia a tu proyecto, incluye lo siguiente en la lista de dependencias, en la parte superior de ViewController.m:

@import GoogleMapsUtils;
  1. Configura el agrupador de marcadores en clústeres.

Para usar este agrupador, debes proporcionar tres elementos a fin de configurar su funcionamiento: un algoritmo de agrupamiento en clústeres, un generador de íconos y un renderizador. El algoritmo determina el comportamiento que define la forma en que se agrupan los marcadores, como la distancia entre los marcadores que se incluirán en el mismo clúster. El generador de íconos proporciona los íconos de clúster que se usarán en los diferentes niveles de zoom. El renderizador controla la renderización real de los íconos de clúster en el mapa.

Si lo prefieres, puedes escribir todos estos elementos desde cero, pero la biblioteca de utilidades de Maps para iOS proporciona implementaciones predeterminadas para facilitar el proceso. Simplemente agrega lo siguiente:

id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];

id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];

id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
  1. Crea una instancia de GMUClusterManager.

GMUClusterManager es la clase que implementa el agrupamiento de marcadores en clústeres con el algoritmo, el generador de íconos y el renderizador que especificaste. Si deseas crear el renderizador y hacer que esté disponible para la vista de mapa, primero agrega una variable de instancia a la implementación de ViewController para almacenar la instancia del administrador de clústeres:

@implementation ViewController {
  GMSMapView *_mapView;
  GMUClusterManager *_clusterManager;
}

A continuación, crea la instancia de GMUClusterManager en el evento de ciclo de vida viewDidLoad:

_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];
  1. Agrega los marcadores y ejecuta el agrupador de marcadores en clústeres.

Ahora que ya configuraste tu instancia del agrupador, solo tienes que pasarle al administrador de clústeres el array de marcadores que se agruparán mediante una llamada a addItems:. Luego, llama a cluster para ejecutar el agrupador.

[_clusterManager addItems:markerArray];
[_clusterManager cluster];

Vuelve a cargar tu app. Ahora deberías ver muchos marcadores, todos armoniosamente agrupados. Puedes pellizcar la pantalla y acercar o alejar el mapa con diferentes niveles de zoom a fin de ver cómo se adaptan los clústeres de marcadores a estas acciones.

c49383b07752bfc4.png

En resumen, en este paso configuraste una instancia del agrupador de marcadores en clústeres de la Biblioteca de utilidades del SDK de Google Maps para iOS y, luego, la usaste para agrupar 100 marcadores en el mapa. El evento de ciclo de vida viewDidLoad en ViewController.m debería verse de la siguiente manera:

- (void)viewDidLoad {
  [super viewDidLoad];

  CLLocationCoordinate2D mapCenter = CLLocationCoordinate2DMake(_mapView.camera.target.latitude,
                                                                _mapView.camera.target.longitude);
  GMSMarker *marker = [GMSMarker markerWithPosition:mapCenter];
  marker.icon = [UIImage imageNamed:@"custom_pin.png"];
  marker.map = _mapView;
  NSArray<GMSMarker *> *markerArray = [LocationGenerator generateMarkersNear:mapCenter count:100];

  id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
  id<GMUClusterIconGenerator> clusterIconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
  id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:clusterIconGenerator];
  _clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer];

  [_clusterManager addItems:markerArray];
  [_clusterManager cluster];
}

8. Agrega interacción del usuario

Ahora tienes un excelente mapa que muestra marcadores y los agrupa en clústeres. En este paso, agregarás algunas acciones para controlar las interacciones del usuario mediante GMSMapViewDelegate, que configuraste con el controlador de vista anteriormente, a fin de mejorar la experiencia del usuario en tu mapa.

El SDK de Maps para iOS proporciona un sistema de eventos completo. Este se implementa a través del delegado de vista de mapa, el cual incluye controladores de eventos que te permiten ejecutar código cuando se producen varias interacciones del usuario. Por ejemplo, el delegado de vista de mapa incluye métodos que te permiten activar la ejecución del código para interacciones tales como cuando el usuario hace clic en el mapa y los marcadores, desplaza lateralmente la vista del mapa, acerca y aleja el mapa, y mucho más.

En este paso, harás que el mapa se desplace lateralmente de manera programática para que el marcador en el que hizo clic el usuario quede en el centro del mapa.

  1. Implementa un objeto de escucha que se activa cuando se presiona un marcador.

Se llama a mapView:didTapMarker cada vez que el usuario presiona uno de los marcadores que creaste anteriormente así como cada vez que presiona un clúster de marcadores (de forma interna, los clústeres de marcadores se implementan como una instancia de GMSMarker).

Para implementar el objeto de escucha de eventos, primero hazlo en forma de stub al final de ViewController.m, antes de la sentencia end.

Notarás que el método devuelve NO. Esto le indica al SDK para iOS que siga ejecutando la funcionalidad GMSMarker predeterminada, como mostrar una ventana de información (si está configurada) después de ejecutar el código de tu controlador de eventos.

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {

  return NO;
}
  1. Establece un control para el evento de presión y anima la cámara para que el mapa vuelva a centrarse cuando se presione un marcador o un clúster de marcadores.

Cuando se llama a mapView:didTapMarker, se pasa la instancia del GMSMarker que se presionó, lo que te permite controlarla en tu código. Puedes usar esta instancia para volver a centrar el mapa mediante una llamada a animateToLocation: en la vista de mapa desde el controlador de eventos. Debes pasarle la posición de la instancia del marcador, que está disponible en la propiedad position.

[_mapView animateToLocation:marker.position];
  1. Acerca la imagen de un clúster de marcadores cuando se lo presiona.

Un patrón común de UX es acercar la imagen de los clústeres de marcadores cuando se los presiona. Esto permite que los usuarios vean los marcadores que integran el clúster, ya que este se expandirá en los niveles de zoom más bajos.

Como se señaló antes, el ícono del clúster de marcadores es solo una implementación de GMSMarker con un ícono personalizado. ¿Cómo puedes saber si se presionó un marcador o un clúster de marcadores? Cuando el administrador de clústeres de marcadores crea un nuevo ícono de clúster, implementa la instancia de GMSMarker de manera tal que cumpla con un protocolo llamado GMUCluster.. Puedes usar un condicional para verificar si el marcador que se pasó al controlador de eventos cumple con este protocolo.

Una vez que sepas de forma programática que se presionó un clúster, podrás llamar a animateToZoom: en la instancia de vista de mapa y establecer que el zoom sea el nivel de zoom actual más uno. El nivel de zoom actual se encuentra disponible en la instancia de vista de mapa, en la propiedad camera.zoom.

Además, observa que el siguiente código devuelve YES. Esto le indica al controlador del evento que finalizó el control del evento y que no debe ejecutar ningún código adicional del controlador. Esto se hace, por ejemplo, para evitar que el objeto GMSMarker subyacente ejecute el resto de su comportamiento predeterminado, como mostrar una ventana de información, lo cual no tendría mucho sentido cuando se presiona un ícono de clúster.

if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
}

Ahora vuelve a cargar la app y presiona algunos marcadores y clústeres de marcadores. En ambos casos, el mapa se volverá a centrar en el elemento seleccionado. Cuando se presione un clúster de marcadores, el mapa también se acercará un nivel y el clúster de marcadores se expandirá para mostrar los que están agrupados debajo.

En resumen, en este paso, implementaste un objeto de escucha que se activa cuando se presiona un marcador, controlaste el evento para que el mapa se volviera a centrar sobre el elemento presionado e hiciste que la imagen se acercara si ese elemento es un ícono de clúster de marcadores.

El método mapView:didTapMarker debería verse de la siguiente manera:

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
  [_mapView animateToLocation:marker.position];

  if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
  }

  return NO;
}

9. Dibuja en el mapa

Hasta ahora, creaste un mapa de Sídney que muestra marcadores en 100 puntos aleatorios y controla la interacción del usuario. En el último paso de este codelab, usarás las funciones de dibujo del SDK de Maps para iOS a fin de agregar una característica útil adicional a la experiencia de tu mapa.

Imagina que a este mapa lo utilizarán usuarios que desean explorar la ciudad de Sídney. Una función útil sería visualizar un radio alrededor de un marcador cuando se hace clic en él. Esto permitiría que el usuario vea rápidamente qué otros destinos están muy cerca del marcador en el que hizo clic, a los cuales puede llegar fácilmente a pie.

El SDK para iOS incluye un conjunto de funciones para dibujar formas sobre el mapa, como cuadrados, polígonos, líneas y círculos. Luego, renderizarás un círculo para mostrar un radio de 800 metros (aproximadamente media milla) alrededor de un marcador cuando se hace clic en él.

  1. Agrega una variable de instancia _circ a la implementación de ViewController.

Esta variable de instancia se usará para guardar el último círculo dibujado, de manera que pueda destruirse antes de que se dibuje otro. Después de todo, no sería muy útil para el usuario y no sería efectivo visualmente si todos los marcadores que se presionaron tuvieran un círculo alrededor.

Para ello, actualiza la implementación de ViewController de la siguiente manera:

@implementation ViewController {
  GMSMapView *_mapView;
  GMUClusterManager *_clusterManager;
  GMSCircle *_circ;
}
  1. Dibuja el círculo cuando se hace presiona un marcador.

En la parte inferior del método mapView:didTapMarker, agrega el siguiente código a fin de crear una instancia de la clase GMSCircle del SDK para iOS que dibuje un nuevo círculo de radio de 800 metros. Para eso, llama a circleWithPosition:radius: y pásale la posición del marcador presionado, tal como lo hiciste antes a fin de volver a centrar el mapa.

_circ = [GMSCircle circleWithPosition:marker.position radius:800];
  1. Elige un estilo para el círculo.

De forma predeterminada, GMSCircle dibuja un círculo con un trazo negro y un relleno transparente. Eso servirá para mostrar el radio, pero su aspecto deja bastante que desear y, además, es un poco difícil de ver. A continuación, asigna un parámetro UIColor a la propiedad fillColor del círculo para definirle un color de relleno a fin de mejorar su estilo. El siguiente código agregará un relleno gris con una transparencia del 50%:

_circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
  1. Renderiza el círculo en el mapa.

Del mismo modo que cuando creaste marcadores antes, notarás que tan solo crear una instancia de GMSCircle no hace que este aparezca en el mapa. Para que se vea, simplemente asigna la instancia de vista de mapa a la propiedad map del círculo.

_circ.map = _mapView;
  1. Quita los círculos renderizados anteriormente.

Tal como se mencionó antes, no brindaríamos una buena experiencia del usuario si simplemente siguiésemos agregando círculos al mapa. Para eliminar el círculo renderizado por un evento de presión anterior, establece la propiedad map de _circ en nil, en la parte superior de mapView:didTapMarker.

_circ.map = nil;

Vuelve a cargar la app y presiona un marcador. Deberías ver que, cada vez que se presiona un marcador, aparece un círculo nuevo y se quita cualquier círculo que se haya renderizado anteriormente.

342520482a888519.png

En resumen, en este paso usaste la clase GMSCircle para renderizar un círculo cada vez que se presiona un marcador.

Tu método mapView:didTapMarker debería verse de la siguiente manera:

- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
  _circ.map = nil;
  [_mapView animateToLocation:marker.position];

  if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) {
    [_mapView animateToZoom:_mapView.camera.zoom +1];
    return YES;
  }

  _circ = [GMSCircle circleWithPosition:marker.position radius:800];
  _circ.fillColor = [UIColor colorWithRed: 0.67 green: 0.67 blue: 0.67 alpha: 0.5];
  _circ.map = _mapView;
  return NO;
}

10. Felicitaciones

Compilaste correctamente tu primera app para iOS con Google Maps Platform, para lo cual aprendiste a cargar el SDK de Maps para iOS y un mapa, a trabajar con marcadores, a controlar el mapa y hacer dibujos sobre él, y a agregar interacción del usuario.

Para ver el código completo, consulta el proyecto finalizado en el directorio /solution.

¿Qué sigue?

En este codelab, viste solo una base de lo que puedes hacer con el SDK de Maps para iOS. Ahora, intenta agregar algunas de estas funciones al mapa:

Si quieres ver más formas de trabajar con Google Maps Platform en la Web, consulta estos vínculos: