1. Antes de comenzar
En este codelab, aprenderás a crear una app para iOS sencilla que use el SDK de Navigation de Google Maps Platform para navegar a un destino preconfigurado.
Así se verá tu app cuando hayas terminado.
Requisitos previos
- Conocimientos básicos sobre el desarrollo de apps para iOS en Swift
- Tener conocimientos básicos sobre los conceptos del SDK de Google Maps, como crear un mapa centrado en una ubicación específica
Qué aprenderás
- Cómo crear una app sencilla de iOS Swift que use el SDK de Navigation para navegar a un destino
- Cómo integrar el SDK de Navigation desde el repositorio remoto de Cocoapods
- Cómo administrar los permisos de ubicación y el acuerdo del usuario con las condiciones del usuario final del SDK de Navigation
- Cómo inicializar el SDK
- Cómo establecer un destino e iniciar la guía de navegación
Requisitos
- La versión estable más reciente de XCode.
- Una Cuenta de Google y un proyecto con facturación habilitada
- Un dispositivo iOS o un dispositivo emulado que se ejecute en el simulador de XCode Cualquiera que elijas, debe cumplir con los requisitos mínimos del SDK de Navigation.
2. Prepárate
Si aún no tienes una cuenta de Google Cloud Platform y un proyecto con la facturación habilitada, configura tu proyecto de Google Cloud siguiendo las instrucciones para comenzar a usar Google Maps Platform.
Selecciona un proyecto de Google Cloud en la consola
En Cloud Console, haz clic en el menú desplegable del proyecto y selecciona el proyecto que deseas usar para este codelab.
Habilita el SDK de Navigation en tu proyecto
Habilita las API y los SDK de Google Maps Platform necesarios para este codelab en Google Cloud Marketplace.
Navega a APIs & Servicios > Biblioteca en la consola de Google Cloud y busca “SDK de Navigation”.
Deberías ver un resultado de la búsqueda.
Haz clic en SDK de Navigation para abrir la página Detalles del producto. Haz clic en Habilitar para habilitar el SDK en tu proyecto.
Repite este proceso para el SDK de Google Maps para iOS.
Crea una clave de API
Genera una clave de API en la página Credenciales de Cloud Console. Todas las solicitudes a Google Maps Platform requieren una clave de API. En la página Credenciales en la consola. Haz clic en “+Crear credenciales”. en la parte superior de la página y selecciona "Clave de API" de las opciones.
Para el uso en producción, se recomienda establecer una restricción de aplicaciones para tu clave de API, pero es opcional para este codelab.
3. Obtén los archivos de proyecto de muestra
En esta sección, se describe cómo configurar un proyecto básico de app de Xcode vacío mediante la clonación de archivos del repositorio de GitHub de este codelab. El repositorio de GitHub contiene versiones anteriores y posteriores del código del codelab. El codelab comenzará con una plantilla de proyecto vacía y se compilará hasta el estado finalizado. Si te quedas atascado, puedes usar el proyecto terminado en el repositorio como referencia.
Clona el repositorio o descarga el código
Navega al directorio en el que deseas almacenar el codelab.
Luego, clona el repositorio o descarga el código:
git clone https://github.com/googlemaps-samples/codelab-navigation-101-ios-swift
Si no tienes Git instalado, haz clic en este botón para obtener el código:
Para que puedas comenzar lo más rápido posible, el repositorio contiene código de partida en la carpeta Starter
que te ayudará a seguir este codelab. También hay un proyecto Solution
terminado en caso de que quieras avanzar o consultar tu progreso en cualquier momento. Para usar el proyecto de solución, deberás seguir las instrucciones de la sección "Instalación con CocoaPods" que se indican a continuación y, luego, ejecuta el comando “pod update” de la carpeta solution/Navigation SDK Codelab
.
Una vez que hayas clonado el repositorio de forma local, usa Xcode para abrir la carpeta Starter
como un proyecto existente. Verifica que el proyecto se compile y se ejecute.
Conecta un dispositivo o configura el simulador de Xcode
4. Agrega el SDK de Navigation a tu app
Existen tres maneras de integrar el SDK de Navigation en un proyecto de Xcode:En este codelab, se usa CocoaPods. Para obtener detalles sobre cómo realizar la integración con Swift Package Manager o para instalarla manualmente descargando el SDK, consulta Cómo crear el proyecto de Xcode e instalar el SDK de Navigation en la documentación del SDK de Navigation.
Cómo instalar con CocoaPods
Si todavía no dispones de la herramienta CocoaPods, instálala en macOS ejecutando el siguiente comando desde el terminal. Para obtener más información, consulta la guía de introducción de CocoaPods.
sudo gem install cocoapods
Crea un archivo nuevo llamado Podfile en la carpeta de tu proyecto, dentro de la carpeta del codelab del SDK de Navigation/starter (en XCode, File > New > File > Other > Empty, save as "Podfile").
Agrega el siguiente contenido a tu Podfile
:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '15.0'
target 'Navigation SDK Codelab' do
pod 'GoogleNavigation', '9.1.1'
end
Ahorra Podfile
.
Abre una terminal y cambia el directorio a la ubicación en la que guardaste tu Podfile (debería ser la carpeta "starter/Navigation SDK Codelab" en el repositorio del codelab).
cd "<path-to-starter-project-folder>/Navigation SDK Codelab"
Ejecuta el comando pod install
. Esto instala las APIs especificadas en el archivo Podfile
, junto con cualquier dependencia.
pod install
Cierra Xcode y, luego, abre el archivo .xcworkspace de tu proyecto para ejecutar Xcode. A partir de este punto, debes usar el archivo .xcworkspace para abrir el proyecto.
Verifica que se haya agregado un directorio de Pods a la estructura del proyecto y que contenga los Pods "GoogleMaps" y "GoogleNavigation".
Agrega tu clave de API
Agrega tu clave de API a AppDelegate.swift
de la siguiente manera:
- Agrega las siguientes instrucciones de importación:
import GoogleMaps
import GoogleNavigation
- Agrega lo siguiente a tu método
application(_:didFinishLaunchingWithOptions:)
:
GMSServices.provideAPIKey("YOUR_API_KEY")
Reemplaza "YOUR_API_KEY" por la clave de API que creaste en el paso anterior.
Compila tu proyecto y corrige los errores.
5. Cómo configurar los permisos de la app
El SDK de Navigation depende de las señales de GPS para proporcionar una ubicación ajustada a la ruta y una guía paso a paso, por lo que tu app deberá solicitarle al usuario que otorgue acceso a datos de ubicación precisa.
Para ello, agregarás algunas propiedades al archivo Info.plist de tu app en Xcode, agregarás código a la app para solicitarle permiso al usuario durante el tiempo de ejecución y controlarás cualquier error, como que no se otorgue el permiso o que la ubicación no esté disponible.
Abre Info.plist en Xcode. Debe verse más o menos así.
Cómo solicitar el permiso de ubicación precisa
Para agregar valores nuevos, coloca el puntero del mouse sobre la fila "Lista de propiedades de información" hasta que aparezca el ícono "+". Haz clic en el signo "+" para ver un diálogo con nombres de propiedades sugeridos, pero ten en cuenta que también puedes agregar propiedades de forma manual.
Agrega las siguientes propiedades y valores al archivo Info.plist:
Propiedad | Valor |
Privacidad: Descripción de uso de la ubicación siempre y cuando está en uso | "Esta app requiere la ubicación de tu dispositivo para proporcionar navegación paso a paso" |
Privacidad: Descripción del uso de la ubicación durante el uso | "Esta app requiere la ubicación de tu dispositivo para proporcionar navegación paso a paso" |
allowsBackgroundLocationUpdates | SÍ |
Cómo solicitar el permiso de ubicación en segundo plano
Agrega las siguientes propiedades y valores al archivo Info.plist:
UIBackgroundModes
Agregar fila > Item 0: App registers for location updates
(selecciona este valor de la lista desplegable de sugerencias)
El archivo Info.plist debería tener un aspecto similar al siguiente cuando termines.
Solicita acceso a la ubicación en el tiempo de ejecución
Agrega las siguientes instrucciones de importación a ViewController.swift
:
import GoogleNavigation
Agrega la siguiente declaración a tu clase ViewController:
var locationManager: CLLocationManager!
Agrega una anulación de método para loadView()
y llama a locationManager.requestAlwaysAuthorization()
:
override func loadView() {
locationManager = CLLocationManager()
locationManager.requestAlwaysAuthorization()
Ahora, tu app solicitará la ubicación del usuario y la pondrá a disposición de tu app si otorga permiso.
Solicita permiso para mostrar notificaciones
Agrega el siguiente código a loadView() para solicitar permiso al usuario para mostrar notificaciones, lo cual será necesario para mostrar las instrucciones de maniobra de navegación.
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) {
granted, error in
// Handle denied authorization to display notifications.
if !granted || error != nil {
print("User rejected request to display notifications.")
}
}
Compila y ejecuta la app, y verifica que se te solicite compartir la ubicación y habilitar las notificaciones.
6. Cómo agregar una interfaz de usuario de navegación
En este paso, agregarás un mapa y lo configurarás para que muestre una ubicación. Luego, le mostrarás al usuario un diálogo con las condiciones de uso del SDK de Navigation.
Cómo agregar una vista de mapa a tu app
Agrega esta línea para declarar una variable GMSMapView en tu ViewController.
var mapView: GMSMapView!
Agrega el siguiente código a loadView()
en tu Viewcontroller.swift
para inicializar el mapa.
let camera = GMSCameraPosition.camera(withLatitude: 51.483174, longitude: -0.177369, zoom: 14)
let options = GMSMapViewOptions()
options.camera = camera
options.frame = .zero
mapView = GMSMapView(options: options)
view = mapView
Compila y ejecuta tu app. Deberías ver un mapa centrado en el suroeste de Londres.
Cómo mostrar el diálogo de Condiciones de uso del producto del SDK de Navigation
Agrega el siguiente código a ViewController.swift
en el mismo método loadView()
que el código anterior. Se mostrarán las condiciones de uso para usuarios finales del SDK de Navigation. Si no se acepta, no se habilitará la navegación.
// Show the terms and conditions.
let companyName = "Navigation SDK Codelab"
GMSNavigationServices.showTermsAndConditionsDialogIfNeeded(withCompanyName: companyName) { termsAccepted in
if termsAccepted {
// Enable navigation if the user accepts the terms.
self.mapView.isNavigationEnabled = true
// Request authorization for alert notifications which deliver guidance instructions
// in the background.
} else {
// Handle the case when the user rejects the terms and conditions.
}
}
Compila y ejecuta la app para ver el diálogo.
7. Agrega objetos de escucha para eventos de navegación clave
En este paso, aprenderás a configurar objetos de escucha para eventos clave, como la llegada a un destino o la redirección del conductor.
Para escuchar estos eventos, tu controlador de vistas debe adoptar el protocolo GMSNavigatorListener
.
Agrega este protocolo a la definición de clase en ViewController.swift
.
class ViewController: UIViewController,
GMSNavigatorListener {
Ahora, agrega una línea de código para configurar el objeto de escucha en loadView():
.
// Add a listener for GMSNavigator.
mapView.navigator?.add(self)
Por último, agrega dos métodos a tu clase para controlar los eventos que se generan.
// Listener to handle arrival events.
func navigator(_ navigator: GMSNavigator, didArriveAt waypoint: GMSNavigationWaypoint) {
print("You have arrived at: \(waypoint.title)")
}
// Listener for route change events.
func navigatorDidChangeRoute(_ navigator: GMSNavigator) {
print("The route has changed.")
}
8. Establece un destino y comienza la guía
En esta sección, aprenderás a establecer un destino e iniciar la guía de navegación.
Crea una función nueva para la lógica de navegación.
Primero, agrega una nueva función llamada startNav()
a tu ViewController
. Contendrá la lógica para establecer un destino y comenzar a navegar.
// Create a route and start guidance.
@objc func startNav() {
}
Crea un Waypoint
para el destino.
A continuación, crea un array de destinos con un solo punto de referencia.
// Create a route and start guidance.
@objc func startNav() {
var destinations = [GMSNavigationWaypoint]()
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
title: "Trafalgar Square")!)
}
Llama a setDestinations()
y controla la respuesta.
A continuación, llama a setDestinations
y controla el GMSRouteStatus
que se muestra.
Si GMSRouteStatus
es "OK", establece isGuidanceActive=true
en el objeto navigator
de mapView
para iniciar la guía. De lo contrario, imprime una instrucción para mostrar que se produjo un error.
Si el valor de GMSRouteStatus
que se muestra es "OK", comienza a simular la conducción a lo largo de la ruta llamando a mapView.locationSimulator.simulateLocationsAlongExistingRoute()
.
// Create a route and start guidance.
@objc func startNav() {
var destinations = [GMSNavigationWaypoint]()
destinations.append(
GMSNavigationWaypoint.init(
placeID: "ChIJH-tBOc4EdkgRJ8aJ8P1CUxo",
title: "Trafalgar Square")!)
mapView.navigator?.setDestinations(
destinations
) { routeStatus in
guard routeStatus == .OK else {
print("Handle route statuses that are not OK.")
return
}
//If routeStatus is OK, start guidance.
self.mapView.navigator?.isGuidanceActive = true
//start simulating driving along the route. self.mapView.locationSimulator?.simulateLocationsAlongExistingRoute()
self.mapView.cameraMode = .following
}
}
Cómo controlar los estados de error comunes
Resulta útil controlar los errores GMSRouteStatus
de forma más explícita, en especial cuando depuras problemas iniciales con la app nueva. Por ejemplo, tal vez descubras que obtienes permiso de ubicación, clave de API o que no se encontró ninguna ruta errores con mayor frecuencia al principio debido a tu configuración de depuración, por lo que puede ser útil manejar estos estados de error.
Agrega un código que controle estos casos específicos y que imprima una sentencia en la consola.
mapView.navigator?.setDestinations(
destinations
) { routeStatus in
guard routeStatus == .OK else {
print("Handle route statuses that are not OK.")
switch routeStatus {
case .locationUnavailable:
print("Location unavailable.") //check permissions
case .noRouteFound:
print("No route found.") //check start location and destination
case .waypointError:
print("Waypoint error") //check Place ID
default:
print("Not sure what happened")
}
return
}
Agrega un botón para iniciar la guía de navegación
Por último, agrega un botón a la IU y conéctalo al método startNav. Crea un método llamado makeButton()
con el siguiente código. Llama a la función makeButton()
desde loadView()
.
// Add a button to the view.
func makeButton() {
// A button to start navigation.
let navButton = UIButton(frame: CGRect(x: 5, y: 150, width: 200, height: 35))
navButton.backgroundColor = .blue
navButton.alpha = 0.5
navButton.setTitle("Start navigation", for: .normal)
navButton.addTarget(self, action: #selector(startNav), for: .touchUpInside)
self.mapView.addSubview(navButton)
}
Compila y ejecuta tu app.
Nota: Ejecutar el código en
startNav()
llamará al
setDestinations()
que genera un cargo después de los primeros 1,000 destinos utilizados. Consulta Uso y facturación para obtener más información.
9. ¡Felicitaciones!
¡Bien hecho! Llegaste a tu destino.
Creaste una app simple que ofrece una guía de navegación paso a paso hacia un destino con el SDK de Navigation de Google Maps Platform.
Ya configuraste los permisos de la app y el diálogo de condiciones para el usuario final del SDK de Navigation, y especificaste un destino con un ID de Place. Controlaste varios estados de éxito y error en tu app.
10. Más información
Si quieres llevar el desarrollo de tu app más allá, echa un vistazo a los siguientes temas para inspirarte.
- Cómo detectar más eventos de navegación Agrega un código para mostrar un mensaje si el tiempo o la distancia restantes supera un umbral.
- Personaliza la interfaz de navegación.
- Si quieres un desafío mayor, intenta agregar un selector de lugares de la API de Places para permitir que el usuario establezca el destino. Sugerencia: Las apps de demostración del SDK de Navigation tienen una implementación de ejemplo. Ejecuta
pod try GoogleNavigation
en la carpeta de tu proyecto para ver el código.