1. Antes de comenzar
En este codelab, aprenderás a usar el SDK de Maps para iOS con SwiftUI.
Requisitos previos
- Conocimientos básicos de Swift
- Conocimientos básicos de SwiftUI
Actividades
- Habilita el SDK de Maps para iOS y utilízalo a fin de agregar mapas de Google Maps a una app para iOS con SwiftUI.
- Agrega marcadores al mapa.
- Pasa el estado de una vista de SwiftUI a un objeto
GMSMapView
y viceversa.
Otros requisitos
- Xcode 11.0 o una versión posterior
- Una Cuenta de Google con facturación habilitada
- SDK de Maps para iOS
- Carthage
2. Prepárate
Para el siguiente 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.
- En Cloud Console, haz clic en el menú desplegable del proyecto y selecciona el proyecto que deseas usar para este codelab.
- 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.
- 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.
3. Descarga el código de inicio
Para que puedas comenzar lo más rápido posible, te ofrecemos un código inicial que te ayudará a seguir este codelab. Puedes pasar directamente a la solución, pero si quieres ir paso a paso para ver cómo crearla tú mismo, sigue leyendo.
- Si tienes
git
instalado, clona el repositorio.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git
También puedes hacer clic en el botón siguiente para descargar el código fuente.
- Después de obtener el código, en una terminal
cd
dentro del directoriostarter/GoogleMapsSwiftUI
, haz lo siguiente: - Ejecuta
carthage update --platform iOS
a fin de descargar el SDK de Maps para iOS. - Por último, abre el archivo
GoogleMapsSwiftUI.xcodeproj
en Xcode.
4. Descripción general del código
En el proyecto inicial que descargaste, se proporcionaron y se implementaron las siguientes clases para ti:
AppDelegate
: elUIApplicationDelegate
de la app (aquí se inicializará el SDK de Maps para iOS)City
: una estructura que representa una ciudad (contiene el nombre y la coordenada de la ciudad)MapViewController
: un UIKitUIViewController
simple que contiene un mapa de Google Maps (GMSMapView)SceneDelegate
: elUIWindowSceneDelegate
de la app desde el que se crea una instancia deContentView
Además, las siguientes clases tienen implementaciones parciales que completarás al final de este codelab:
ContentView
: la vista de SwiftUI de nivel superior que contiene a tu appMapViewControllerBridge
: una clase que vincula una vista de UIKit a una vista de SwiftUI (específicamente, esta es la clase que hará queMapViewController
sea accesible en SwiftUI)
5. Cómo usar SwiftUI en comparación con UIKit
SwiftUI se introdujo en iOS 13 como un marco de trabajo de IU alternativo en lugar de UIKit a fin de desarrollar apps para iOS. En comparación con su predecesor, SwiftUI ofrece varias ventajas. A continuación, te mostramos algunas de ellas:
- Las vistas se actualizan automáticamente cuando cambia el estado. Si usas los objetos denominados State, cualquier cambio en el valor subyacente que contienen hará que la IU se actualice automáticamente.
- Las vistas previas en vivo permiten un desarrollo más rápido. Las vistas previas en vivo minimizan la necesidad de compilar e implementar código en un emulador con el fin de que se produzcan cambios visuales, ya que se puede obtener fácilmente una vista previa de SwiftUI en Xcode.
- La fuente de confianza está en Swift. Todas las vistas en SwiftUI se declaran en Swift, por lo que ya no es necesario usar el compilador de interfaz.
- SwiftUI interactúa con UIKit. La interoperabilidad con UIKit garantiza que las apps existentes puedan usar SwiftUI de forma incremental con sus vistas actuales. Además, las bibliotecas que aún no admiten SwiftUI, como el SDK de Maps para iOS, sí se pueden usar en SwiftUI.
También existen algunas desventajas:
- SwiftUI solo está disponible en iOS 13 y versiones posteriores.
- La jerarquía de vistas no se puede examinar en las vistas previas de Xcode.
Estado y flujo de datos de SwiftUI
SwiftUI ofrece una novedosa manera de crear IU con un enfoque declarativo: le dices a SwiftUI cuál quieres que sea la vista junto con todos sus diferentes estados, y el sistema hará el resto. SwiftUI se encarga de actualizar la vista cuando el estado subyacente cambia debido a un evento o a una acción del usuario. Este diseño se conoce comúnmente como flujo de datos unidireccional. Si bien los detalles específicos de este diseño están fuera del alcance de este codelab, te recomendamos que leas en detalle cómo funciona esto en la documentación de Apple sobre el estado y el flujo de datos.
Cómo conectar UIKit y SwiftUI con UIViewRepresentable o UIViewControllerRepresentable
Dado que el SDK de Maps para iOS se desarrolló a partir de UIKit y aún no proporciona una vista compatible con SwiftUI, para usarlo en SwiftUI, se requiere de UIViewRepresentable
o UIViewControllerRepresentable
. Estos protocolos permiten que SwiftUI incluya las UIView
y los UIViewController
compilados en UIKit, respectivamente. Si bien puedes usar cualquiera de los protocolos para agregar un mapa de Google Maps a una vista de SwiftUI, en el siguiente paso, analizaremos cómo usar UIViewControllerRepresentable
para incluir un UIViewController
que contenga un mapa.
6. Agrega un mapa
En esta sección, agregarás mapas de Google Maps a una vista de SwiftUI.
Agrega tu clave de API
Debes proporcionar al SDK de Maps para iOS la clave de API que creaste en un paso anterior a fin de asociar tu cuenta con el mapa que se mostraría en la app.
Para proporcionar tu clave de API, abre el archivo AppDelegate.swift
y navega al método application(_, didFinishLaunchingWithOptions)
. Actualmente, el SDK se inicializa a través de GMSServices.provideAPIKey()
con la string "YOUR_API_KEY". Reemplaza esa string por la clave de API. Al completar este paso, se inicializará el SDK de Maps para iOS cuando se inicie la aplicación.
Agrega un mapa de Google Maps con MapViewControllerBridge
Ahora que se proporciona tu clave de API al SDK, el siguiente paso es mostrar el mapa en la app.
Actualmente, el controlador de vista MapViewController
que se proporciona en el código de inicio contiene GMSMapView
en su vista. Sin embargo, como este controlador de vista se creó en UIKit, deberás conectar esta clase a SwiftUI para que se pueda usar dentro de ContentView
. Para ello, sigue estos pasos:
- Abre el archivo
MapViewControllerBridge
en Xcode.
Esta clase se ajusta a UIViewControllerRepresentable, que es el protocolo que se necesita para la unión con un UIViewController
de UIKit, de modo que se pueda usar como una vista de SwiftUI. En otras palabras, cumplir con este protocolo te permite establecer una vinculación entre una vista de UIKit y una de SwiftUI, y requiere de los siguientes dos métodos:
makeUIViewController(context)
: SwiftUI llama a este método para crear elUIViewController
subyacente. Aquí, crearás una instancia deUIViewController
y la pasarás a su estado inicial.updateUIViewController(_, context)
: SwiftUI llama a este método cada vez que cambia el estado. Aquí es donde harías cualquier modificación en elUIViewController
subyacente a fin de reaccionar en respuesta al cambio de estado.
- Crea un
MapViewController
Dentro de la función makeUIViewController(context)
, crea una instancia nueva de MapViewController
y muéstrala como resultado. Después de hacerlo, tu MapViewControllerBridge
debería verse de la siguiente manera:
MapViewControllerBridge
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
}
}
Usa MapViewControllerBridge en ContentView
Ahora que MapViewControllerBridge
está creando una instancia de MapViewController
, el siguiente paso es usar esta estructura dentro de ContentView
para mostrar un mapa.
- Abre el archivo
ContentView
en Xcode.
Las instancias de ContentView
se crean en SceneDelegate
y contienen la vista de las apps de nivel superior. El mapa se agregará desde este archivo.
- Crea un
MapViewControllerBridge
dentro de la propiedadbody
.
En la propiedad body
de este archivo, ya se proporcionó y se implementó un ZStack
para ti. Actualmente, ZStack
contiene una lista de ciudades interactiva y arrastrable que usarás en un paso posterior. Por ahora, dentro de ZStack
, crea un MapViewControllerBridge
como la primera vista secundaria de ZStack
, de modo que se muestre un mapa en la app, detrás de la vista de la lista de ciudades. Después de este paso, el contenido de la propiedad body
dentro de ContentView
debería verse de la siguiente manera:
ContentView
var body: some View {
let scrollViewHeight: CGFloat = 80
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge()
// Cities List
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
self.zoomInCenter = false
self.expandList = false
} handleAction: {
self.expandList.toggle()
} // ...
}
}
}
- Ahora, ejecuta la app. Deberías ver que el mapa se carga en la pantalla de tu dispositivo, junto con una lista de ciudades que se puede arrastrar hacia la parte inferior de la pantalla.
7. Agrega marcadores al mapa
En el paso anterior, agregaste un mapa junto a una lista interactiva que muestra distintas ciudades. En esta sección, agregarás marcadores para cada ciudad de esa lista.
Marcadores como estado
Actualmente, ContentView
declara una propiedad denominada markers
, que es una lista de GMSMarker
que representa cada ciudad declarada en la propiedad estática cities
. Ten en cuenta que esta propiedad está anotada con el wrapper State de la propiedad de SwiftUI a fin de indicar que debe administrarse mediante SwiftUI. Por lo tanto, si se detecta algún cambio en esta propiedad, como agregar o quitar un marcador, se actualizarán las vistas que usen este estado.
ContentView
static let cities = [
City(name: "San Francisco", coordinate: CLLocationCoordinate2D(latitude: 37.7576, longitude: -122.4194)),
City(name: "Seattle", coordinate: CLLocationCoordinate2D(latitude: 47.6131742, longitude: -122.4824903)),
City(name: "Singapore", coordinate: CLLocationCoordinate2D(latitude: 1.3440852, longitude: 103.6836164)),
City(name: "Sydney", coordinate: CLLocationCoordinate2D(latitude: -33.8473552, longitude: 150.6511076)),
City(name: "Tokyo", coordinate: CLLocationCoordinate2D(latitude: 35.6684411, longitude: 139.6004407))
]
/// State for markers displayed on the map for each city in `cities`
@State var markers: [GMSMarker] = cities.map {
let marker = GMSMarker(position: $0.coordinate)
marker.title = $0.name
return marker
}
Observa que ContentView
usa la propiedad markers
para renderizar la lista de ciudades; para ello, la pasa a la clase CitiesList
.
CitiesList
struct CitiesList: View {
@Binding var markers: [GMSMarker]
var body: some View {
GeometryReader { geometry in
VStack(spacing: 0) {
// ...
// List of Cities
List {
ForEach(0..<self.markers.count) { id in
let marker = self.markers[id]
Button(action: {
buttonAction(marker)
}) {
Text(marker.title ?? "")
}
}
}.frame(maxWidth: .infinity)
}
}
}
}
Pasa el estado a MapViewControllerBridge a través de una vinculación
Además de la lista de ciudades que muestra datos de la propiedad markers
, pasa esta propiedad a la estructura de MapViewControllerBridge
, de modo que se pueda usar a fin de mostrar esos marcadores en el mapa. Para eso, sigue estos pasos:
- Declara una nueva propiedad
markers
dentro deMapViewControllerBridge
con la anotación@Binding
.
MapViewControllerBridge
struct MapViewControllerBridge: : UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
// ...
}
- En
MapViewControllerBridge
, actualiza el métodoupdateUIViewController(_, context)
para poder usar la propiedadmarkers
.
Como se mencionó en el paso anterior, SwiftUI llamará a updateUIViewController(_, context)
cada vez que cambie el estado. Debemos actualizar el mapa dentro de este método con el fin de que se muestren los marcadores en markers
. Para ello, deberás actualizar la propiedad map
de cada marcador. Después de completar este paso, tu MapViewControllerBridge
debería verse así:
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
// Update the map for each marker
markers.forEach { $0.map = uiViewController.map }
}
}
- Pasa la propiedad
markers
deContentView
aMapViewControllerBridge
Como agregaste una propiedad nueva en MapViewControllerBridge
, ahora se requiere que se pase el valor de esta propiedad en el inicializador de MapViewControllerBridge
. Por lo tanto, si intentas compilar la app, notarás que no será posible. Para corregir esto, actualiza la ContentView
en donde se crea MapViewControllerBridge
y pasa la propiedad markers
de la siguiente manera:
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers)
// ...
}
}
}
}
Observa que el prefijo $
se usó para pasar markers
a MapViewControllerBridge
, ya que espera una propiedad vinculada. $
es un prefijo reservado para usar con wrappers de propiedades de Swift. Cuando se aplica a un estado, muestra una vinculación.
- Ejecuta la app para ver los marcadores que se muestran en el mapa.
8. Crea una animación de la ciudad seleccionada
En el paso anterior, agregaste marcadores a un mapa pasando el estado de una vista de SwiftUI a otra. En este paso, animarás la imagen de una ciudad o de un marcador después de que se haya presionado en la lista interactiva. Para realizar la animación, debes reaccionar a los cambios de un estado modificando la posición de la cámara del mapa cuando se produzcan los cambios. Para obtener más información sobre el concepto de la cámara del mapa, consulta Cámara y vista.
Crea una animación en el mapa de una ciudad seleccionada
Para crear una animación en el mapa de una ciudad seleccionada, completa este paso:
- Define una nueva vinculación en
MapViewControllerBridge
.
ContentView
tiene una propiedad de estado denominada selectedMarker
que se inicializa en nil y se actualiza cada vez que se selecciona una ciudad en la lista. Esto se controla mediante buttonAction
en la vista CitiesList
dentro de ContentView
.
ContentView
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
// ...
}
Cada vez que cambie selectedMarker
, MapViewControllerBridge
debería tener en cuenta este cambio de estado para que pueda crear una animación en el mapa del marcador seleccionado. Por lo tanto, define una nueva vinculación dentro de MapViewControllerBridge
del tipo GMSMarker
y asigna un nombre a la propiedad selectedMarker
.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
}
- Actualiza
MapViewControllerBridge
para animar el mapa cada vez que cambieselectedMarker
.
Una vez que se declara una nueva vinculación, debes actualizar la función updateUIViewController_, context)
de MapViewControllerBridge
para que el mapa tenga la animación del marcador seleccionado. Para ello, copie el siguiente código:
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
markers.forEach { $0.map = uiViewController.map }
selectedMarker?.map = uiViewController.map
animateToSelectedMarker(viewController: uiViewController)
}
private func animateToSelectedMarker(viewController: MapViewController) {
guard let selectedMarker = selectedMarker else {
return
}
let map = viewController.map
if map.selectedMarker != selectedMarker {
map.selectedMarker = selectedMarker
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(toZoom: kGMSMinZoomLevel)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
map.animate(toZoom: 12)
})
}
}
}
}
}
La función animateToSelectedMarker(viewController)
realizará una secuencia de animaciones de mapas con la función animate(with)
de GMSMapView
.
- Pasa el
selectedMarker
deContentView
aMapViewControllerBridge
Una vez que MapViewControllerBridge
tenga la nueva vinculación declarada, actualiza ContentView
para pasar el selectedMarker
en el que se crea una instancia de MapViewControllerBridge
.
ContentView
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
// ...
}
}
}
}
Ahora, cuando completes este paso, se creará una animación en el mapa cada vez que se seleccione una ciudad nueva en la lista.
Crea una animación en la vista de SwiftUI para destacar la ciudad
SwiftUI facilita mucho la animación de vistas, ya que se encarga de realizar las animaciones de transiciones de estado. Para demostrar esto, agregarás más animaciones enfocando la vista a la ciudad seleccionada después de que se complete la animación en el mapa. Completa los siguientes pasos:
- Agrega un cierre de
onAnimationEnded
aMapViewControllerBridge
.
Debido a que la animación de SwiftUI se realizará después de la secuencia de animación en el mapa que agregaste anteriormente, declara un nuevo cierre con el nombre onAnimationEnded
dentro de MapViewControllerBridge
y, luego, invoca este cierre después de una demora de 0.5 segundos posterior a la última animación en el mapa dentro del método animateToSelectedMarker(viewController)
.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var onAnimationEnded: () -> ()
private func animateToSelectedMarker(viewController: MapViewController) {
guard let selectedMarker = selectedMarker else {
return
}
let map = viewController.map
if map.selectedMarker != selectedMarker {
map.selectedMarker = selectedMarker
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(toZoom: kGMSMinZoomLevel)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
map.animate(toZoom: 12)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
// Invoke onAnimationEnded() once the animation sequence completes
onAnimationEnded()
})
})
}
}
}
}
}
- Implementa
onAnimationEnded
enMapViewControllerBridge
.
Implementa el cierre onAnimationEnded
en el que se crean instancias de MapViewControllerBridge
dentro de ContentView
. Copia y pega el siguiente código, que agrega un nuevo estado denominado zoomInCenter
, modifica la vista mediante clipShape
y, además, varía el diámetro de la forma recortada según el valor de zoomInCenter
.
ContentView
struct ContentView: View {
@State var zoomInCenter: Bool = false
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
self.zoomInCenter = true
})
.clipShape(
Circle()
.size(
width: diameter,
height: diameter
)
.offset(
CGPoint(
x: (geometry.size.width - diameter) / 2,
y: (geometry.size.height - diameter) / 2
)
)
)
.animation(.easeIn)
.background(Color(red: 254.0/255.0, green: 1, blue: 220.0/255.0))
}
}
}
}
- Ejecuta la app para ver las animaciones.
9. Envía un evento a SwiftUI
En este paso, escucharás eventos emitidos desde GMSMapView
y los enviarás a SwiftUI. Específicamente, establecerás un delegado en la vista de mapa y escucharás los eventos de movimiento de la cámara, de modo que, cuando una ciudad se enfoque y la cámara del mapa se mueva por un gesto, esta vista perderá el enfoque para que puedas ver más partes del mapa.
Cómo usar los coordinadores de SwiftUI
GMSMapView
emite eventos como cuando se cambia la posición de la cámara o cuando se presiona un marcador. El mecanismo para escuchar estos eventos funciona con el protocolo GMSMapViewDelegate. SwiftUI presenta el concepto de un coordinador que actúa específicamente como el delegado de los controladores de vista de UIKit. Por lo tanto, en el mundo de SwiftUI, el coordinador debe encargarse de cumplir con el protocolo GMSMapViewDelegate
. Para hacerlo, sigue los pasos que se indican a continuación:
- Crea un coordinador con el nombre
MapViewCoordinator
dentro deMapViewControllerBridge
.
Crea una clase anidada dentro de la clase MapViewControllerBridge
y llámala MapViewCoordinator
. Esta clase debe cumplir con GMSMapViewDelegate
y declarar MapViewControllerBridge
como una propiedad.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
var mapViewControllerBridge: MapViewControllerBridge
init(_ mapViewControllerBridge: MapViewControllerBridge) {
self.mapViewControllerBridge = mapViewControllerBridge
}
}
}
- Implementa
makeCoordinator()
enMapViewControllerBridge
.
A continuación, implementa el método makeCoordinator()
dentro de MapViewControllerBridge
y muestra una instancia del MapViewCoodinator
que creaste en el paso anterior.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeCoordinator() -> MapViewCoordinator {
return MapViewCoordinator(self)
}
}
- Configura
MapViewCoordinator
como el delegado de la vista de mapa.
Después de crear el coordinador personalizado, el próximo paso es establecerlo como el delegado de la vista de mapa del controlador de vista. Para ello, actualiza la inicialización del controlador de vista en makeUIViewController(context)
. Se podrá acceder al coordinador creado en el paso anterior desde el objeto Context.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
uiViewController.map.delegate = context.coordinator
return uiViewController
}
- Agrega un cierre en
MapViewControllerBridge
para que el evento de movimiento de la cámara se propague hacia arriba.
Dado que el objetivo es actualizar la vista con los movimientos de la cámara, declara una nueva propiedad de cierre que acepte un valor booleano dentro de MapViewControllerBridge
con el nombre mapViewWillMove
y, luego, invoca este cierre en el método delegado mapView(_, willMove)
dentro de MapViewCoordinator
. Pasa el valor de gesture
al cierre, de modo que la vista de SwiftUI pueda reaccionar solo a los eventos de movimiento de la cámara relacionados con gestos.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var mapViewWillMove: (Bool) -> ()
//...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
// ...
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
self.mapViewControllerBridge.mapViewWillMove(gesture)
}
}
}
- Actualiza ContentView para pasar un valor de
mapWillMove
.
Con el nuevo cierre declarado en MapViewControllerBridge
, actualiza ContentView
a fin de pasar un valor para este nuevo cierre. Dentro de ese cierre, cambia el estado de zoomInCenter
a false
si el evento de movimiento está relacionado con un gesto. De este modo, el mapa volverá a verse completamente cuando se mueva con un gesto.
ContentView
struct ContentView: View {
@State var zoomInCenter: Bool = false
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
self.zoomInCenter = true
}, mapViewWillMove: { (isGesture) in
guard isGesture else { return }
self.zoomInCenter = false
})
// ...
}
}
}
}
- Ejecuta la app para ver los nuevos cambios.
10. Felicitaciones
Felicitaciones por haber llegado hasta aquí. Abarcaste una gran cantidad de temas y esperamos que las lecciones que aprendiste te permitan compilar tu propia app de SwiftUI mediante el SDK de Maps para iOS.
Lo que aprendiste
- Las diferencias entre SwiftUI y UIKit
- Cómo vincular SwiftUI y UIKit mediante UIViewControllerRepresentable
- Cómo realizar cambios de estado y vinculación en la vista de mapa
- Cómo enviar un evento de la vista de mapa a SwiftUI usando un coordinador
¿Qué sigue?
- SDK de Maps para iOS: Documentación oficial
- SDK de Places para iOS: Cómo encontrar empresas locales y lugares de interés cerca de tu ubicación
- maps-sdk-for-ios-samples: Código de muestra en GitHub que incluye todas las funciones dentro del SDK de Maps para iOS
- SwiftUI: Documentación oficial de Apple
- Responde esta pregunta para ayudarnos a crear el contenido que te resultaría más útil:
¿Qué otros codelabs te gustaría ver?
¿El codelab que quieres no figura arriba? Crea un nuevo problema aquí para solicitarlo.