1. Antes de começar
Este codelab ensina como usar o SDK do Maps para iOS com o SwiftUI.
Pré-requisitos
- Conhecimento básico de Swift
- Noções básicas de SwiftUI
Atividades deste codelab
- Ativar e usar o SDK do Maps para iOS para adicionar o Google Maps a um app iOS usando o SwiftUI
- Adicionar marcadores ao mapa
- Transmitir o estado de uma visualização do SwiftUI para um objeto
GMSMapView
e vice-versa.
Pré-requisitos
- Xcode 11.0 ou posterior
- Uma Conta do Google com faturamento ativado
- SDK do Maps para iOS
- Carthage
2. Começar a configuração
Para a etapa a seguir, ative o SDK do Maps para iOS.
Configurar a Plataforma Google Maps
Caso você ainda não tenha uma conta do Google Cloud Platform e um projeto com faturamento ativado, veja como criá-los no guia Primeiros passos com a Plataforma Google Maps.
- No Console do Cloud, clique no menu suspenso do projeto e selecione o projeto que você quer usar neste codelab.
- Ative as APIs e os SDKs da Plataforma Google Maps necessários para este codelab no Google Cloud Marketplace. Para fazer isso, siga as etapas descritas neste vídeo ou nesta documentação.
- Gere uma chave de API na página Credenciais do Console do Cloud. Siga as etapas indicadas neste vídeo ou nesta documentação. Todas as solicitações à Plataforma Google Maps exigem uma chave de API.
3. Fazer o download do código inicial
Veja aqui o código inicial para ajudar você a acompanhar este codelab e começar o mais rápido possível. Se preferir, você pode ir direto para a solução, mas continue lendo se quiser desenvolver por conta própria.
- Clone o repositório se você tiver o
git
instalado.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git
Se preferir, clique no botão a seguir para fazer o download do código-fonte.
- Ao receber o código, abra um terminal
cd
no diretóriostarter/GoogleMapsSwiftUI
. - Execute
carthage update --platform iOS
para fazer o download do SDK do Maps para iOS. - Por fim, abra o arquivo
GoogleMapsSwiftUI.xcodeproj
no Xcode.
4. Visão geral do código
No projeto inicial que você salvou, as seguintes classes foram incluídas e implementadas para você:
AppDelegate
: oUIApplicationDelegate
do aplicativo. É aqui que o SDK do Maps para iOS será inicializado.City
: uma struct que representa uma cidade (contém um nome e uma coordenada da cidade).MapViewController
: um UIKitUIViewController
simples contendo um mapa do Google Map (GMSMapView).SceneDelegate
: oUIWindowSceneDelegate
do aplicativo a partir do qualContentView
é instanciado.
Além disso, as seguintes classes têm implementações parciais que serão concluídas ao final deste codelab:
ContentView
: a visualização de nível superior do SwiftUI contendo seu app.MapViewControllerBridge
: uma classe que cria uma ponte entre uma visualização do UIKit e uma visualização do SwiftUI. Especificamente, essa é a classe que tornará oMapViewController
acessível no SwiftUI.
5. Diferenças entre SwiftUI e UIKit
O SwiftUI foi introduzido no iOS 13 como uma alternativa ao UIKit, um framework de UI para desenvolvimento de aplicativos iOS. Em comparação com o UIKit, seu antecessor, o SwiftUI oferece várias vantagens. Para citar alguns:
- As visualizações são atualizadas automaticamente quando o estado muda. Usando objetos chamados State, qualquer alteração no valor contido fará com que a IU seja atualizada automaticamente.
- As visualizações em tempo real permitem um desenvolvimento mais rápido. Elas minimizam a necessidade de criar e implantar código em um emulador para gerar alterações visuais, já que uma pré-visualização do SwiftUI pode ser exibida prontamente no Xcode.
- A fonte da verdade está em Swift. Todas as visualizações no SwiftUI são declaradas em Swift. Portanto, o uso do Interface Builder não é mais necessário.
- Funciona com o UIKit. A interoperabilidade com o UIKit garante que os apps existentes possam usar o SwiftUI de maneira incremental com as visualizações existentes. Além disso, bibliotecas que ainda não são compatíveis com o SwiftUI, como o SDK do Maps para iOS, podem ser usadas mesmo assim.
Mas também há desvantagens:
- O SwiftUI só está disponível no iOS 13 ou posterior.
- A hierarquia de visualização não pode ser examinada em prévias do Xcode.
Estado e fluxo de dados no SwiftUI
O SwiftUI oferece uma nova maneira de criar IU usando uma abordagem declarativa. Você diz a ele como quer exibir a visualização com todos os diferentes estados, e o sistema fará o resto. O SwiftUI atualiza a visualização sempre que o estado contido muda devido a um evento ou uma ação do usuário. Isso é comumente chamado de fluxo de dados unidirecional. Embora as especificidades desse design estejam fora do escopo deste codelab, recomendamos ler mais sobre como isso funciona na documentação de Estado e fluxo de dados da Apple.
Ponte entre o UIKit e o SwiftUI usando UIViewRepresentable ou UIViewControllerRepresentable
Como o SDK do Maps para iOS é criado com base no UIKit e ainda não oferece uma visualização compatível com o SwiftUI, usá-lo no SwiftUI exige conformidade com UIViewRepresentable
ou UIViewControllerRepresentable
. Esses protocolos permitem que o SwiftUI inclua UIView
s e UIViewController
s criados no UIKit, respectivamente. Você pode usar qualquer um deles para adicionar um mapa do Google Maps a uma visualização do SwiftUI, mas na próxima etapa veremos especificamente como usar UIViewControllerRepresentable
para incluir um UIViewController
contendo um mapa.
6. Adicionar um mapa
Nesta seção, você irá adicionar o Google Maps a uma visualização do SwiftUI.
Adicionar sua chave de API
A chave de API que você criou em uma etapa anterior precisa ser informada ao SDK do Maps para iOS para associar sua conta ao mapa que será exibido no app.
Para inserir sua chave de API, abra o arquivo AppDelegate.swift
e navegue até o método application(_, didFinishLaunchingWithOptions)
. No momento, o SDK é inicializado usando GMSServices.provideAPIKey()
com a string "YOUR_API_KEY". Substitua-a pela sua chave de API. Ao concluir essa etapa, o SDK do Maps para iOS será inicializado quando o aplicativo for iniciado.
Adicionar um mapa do Google Maps usando MapViewControllerBridge
Agora que sua chave de API está sendo informada ao SDK, a próxima etapa é exibir o mapa no app.
O controlador de visualizações MapViewController
, incluído no código inicial, contém um GMSMapView
na visualização. No entanto, como esse controlador foi criado no UIKit, será necessário fazer uma ponte dessa classe para o SwiftUI para que ela possa ser usada no ContentView
. Basta seguir estas etapas:
- Abra o arquivo
MapViewControllerBridge
no Xcode.
Essa classe está em conformidade com o UIViewControllerRepresentable, que é o protocolo necessário para fazer um wrap do UIViewController
do UIKit para ser usado como uma visualização do SwiftUI. Em outras palavras, obedecer a esse protocolo permite fazer uma ponte de uma visualização do UIKit para uma visualização do SwiftUI. A conformidade com esse protocolo exige a implementação de dois métodos:
makeUIViewController(context)
: esse método é chamado pelo SwiftUI para criar oUIViewController
subjacente. É aqui que você iria instanciar seuUIViewController
e transmitir a ele o estado inicial.updateUIViewController(_, context)
: esse método é chamado pelo SwiftUI sempre que o estado muda. É aqui que você faria qualquer modificação noUIViewController
subjacente para reagir em resposta à mudança de estado.
- Crie um
MapViewController
.
Dentro da função makeUIViewController(context)
, instancie um novo MapViewController
e retorne-o como resultado. Depois disso, seu MapViewControllerBridge
ficará assim:
MapViewControllerBridge
import GoogleMaps
import SwiftUI
struct MapViewControllerBridge: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> MapViewController {
return MapViewController()
}
func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
}
}
Usar MapViewControllerBridge no ContentView
Agora que o MapViewControllerBridge
está criando uma instância do MapViewController
, a próxima etapa é usar essa struct dentro do ContentView
para exibir um mapa.
- Abra o arquivo
ContentView
no Xcode.
O ContentView
é instanciado no SceneDelegate
e contém a visualização de nível superior do aplicativo. O mapa será adicionado de dentro deste arquivo.
- Crie um
MapViewControllerBridge
dentro da propriedadebody
.
Dentro da propriedade body
desse arquivo, um ZStack
já foi incluído e implementado. No momento, o ZStack
contém uma lista de cidades interativa e arrastável que você vai usar em uma etapa posterior. Por enquanto, dentro do ZStack
, crie um MapViewControllerBridge
como a primeira visualização filha do ZStack
para que um mapa seja exibido no app atrás da lista de cidades. Depois disso, o conteúdo da propriedade body
dentro do ContentView
ficará assim:
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()
} // ...
}
}
}
- Agora, execute o app. Você verá o mapa ser carregado na tela do dispositivo com uma lista arrastável de cidades na parte inferior da tela.
7. Adicionar marcadores ao mapa
Na etapa anterior, você adicionou um mapa com uma lista interativa de cidades. Nesta seção, você irá adicionar marcadores a cada cidade da lista.
Marcadores como estado
No momento, o ContentView
declara uma propriedade chamada markers
, que é uma lista do GMSMarker
que representa cada cidade declarada na propriedade estática cities
. Essa propriedade é anotada com o wrapper de propriedade do SwiftUI State para indicar que ela deve ser gerenciada pelo SwiftUI. Portanto, se forem detectadas alterações nessa propriedade, como adição ou remoção de um marcador, as visualizações que usarem esse estado serão atualizadas.
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
}
Observe que o ContentView
usa a propriedade markers
para renderizar a lista de cidades transmitindo-a para a classe 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)
}
}
}
}
Transmitir estado para MapViewControllerBridge por Binding
Além da lista de cidades que exibem dados da propriedade markers
, transmita essa propriedade para a struct MapViewControllerBridge
para que ela possa ser usada para exibir esses marcadores no mapa. Para fazer isso, siga estas etapas:
- Declare uma nova propriedade
markers
dentro doMapViewControllerBridge
anotada com@Binding
.
MapViewControllerBridge
struct MapViewControllerBridge: : UIViewControllerRepresentable {
@Binding var markers: [GMSMarker]
// ...
}
- No
MapViewControllerBridge
, atualize o métodoupdateUIViewController(_, context)
para usar a propriedademarkers
.
Como mencionado na etapa anterior, o updateUIViewController(_, context)
será chamado pelo SwiftUI sempre que o estado mudar. É dentro desse método que queremos atualizar o mapa, então exiba os marcadores em markers
. Para fazer isso, você precisará atualizar a propriedade map
de cada marcador. Depois de concluir essa etapa, o MapViewControllerBridge
ficará assim:
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 }
}
}
- Transmita a propriedade
markers
doContentView
para oMapViewControllerBridge
Como você adicionou uma nova propriedade no MapViewControllerBridge
, agora é necessário que o valor dela seja transmitido no inicializador para o MapViewControllerBridge
. Portanto, se você tentar criar o app, perceberá que ele não será compilado. Para corrigir isso, atualize o ContentView
onde o MapViewControllerBridge
é criado e transmita a propriedade markers
da seguinte maneira:
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers)
// ...
}
}
}
}
O prefixo $
foi usado para transmitir markers
para o MapViewControllerBridge
, já que ele espera uma propriedade vinculada por Binding. $
é um prefixo reservado para uso com wrappers de propriedade do Swift. Quando aplicado a um estado, ele retornará um Binding.
- Execute o app para ver os marcadores exibidos no mapa.
8. Animar para uma cidade selecionada
Na etapa anterior, você adicionou marcadores a um mapa transmitindo o estado de uma visualização do SwiftUI para outra. Nesta etapa, você irá criar uma animação para quando o usuário toca em uma cidade/marcador na lista interativa. Para isso, você irá reagir às mudanças de um estado modificando a posição da câmera no mapa quando a alteração ocorrer. Para saber mais sobre o conceito da câmera no mapa, consulte Câmera e visualização.
Animar mapa para a cidade selecionada
Para animar o mapa para uma cidade selecionada:
- Defina um novo Binding em
MapViewControllerBridge
.
O ContentView
tem uma propriedade de estado chamada selectedMarker
, que é inicializada como nula e é atualizada sempre que uma cidade é selecionada na lista. Isso é processado pela visualização buttonAction
de CitiesList
dentro do ContentView
.
ContentView
CitiesList(markers: $markers) { (marker) in
guard self.selectedMarker != marker else { return }
self.selectedMarker = marker
// ...
}
Sempre que selectedMarker
mudar, o MapViewControllerBridge
precisará estar ciente dessa mudança de estado para animar o mapa para o marcador selecionado. Portanto, defina um novo Binding dentro do MapViewControllerBridge
do tipo GMSMarker
e nomeie a propriedade selectedMarker
.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
@Binding var selectedMarker: GMSMarker?
}
- Atualize o
MapViewControllerBridge
para animar o mapa sempre queselectedMarker
mudar.
Depois que um novo Binding for declarado, será necessário atualizar a função updateUIViewController_, context)
do MapViewControllerBridge
para que o mapa seja animado para o marcador selecionado. Para fazer isso, copie o código abaixo:
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)
})
}
}
}
}
}
A função animateToSelectedMarker(viewController)
irá executar uma sequência de animações no mapa usando a função animate(with)
do GMSMapView
.
- Transmita
selectedMarker
doContentView
para oMapViewControllerBridge
.
Depois que o MapViewControllerBridge
tiver o novo Binding declarado, atualize o ContentView
para transmitir o selectedMarker
para onde o MapViewControllerBridge
estiver instanciado.
ContentView
struct ContentView: View {
// ...
var body: some View {
// ...
GeometryReader { geometry in
ZStack(alignment: .top) {
// Map
MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
// ...
}
}
}
}
Após concluir esta etapa, o usuário verá uma animação sempre que uma nova cidade for selecionada na lista.
Animar visualização do SwiftUI para enfatizar a cidade
O SwiftUI facilita a animação de visualizações, já que ele processa animações para transições de estado. Para demonstrar isso, você irá adicionar mais animações concentrando a visualização na cidade selecionada após a conclusão da animação do mapa. Para isso, siga os seguintes passos:
- Adicione uma clausura de
onAnimationEnded
aoMapViewControllerBridge
.
Como a animação do SwiftUI será realizada após a sequência de animações do mapa que você adicionou antes, declare uma nova clausura chamada onAnimationEnded
dentro do MapViewControllerBridge
e invoque essa clausura depois de uma latência de 0,5 segundos após a última animação do mapa dentro do 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()
})
})
}
}
}
}
}
- Implemente
onAnimationEnded
noMapViewControllerBridge
.
Implemente a clausura onAnimationEnded
onde o MapViewControllerBridge
estiver instanciado dentro do ContentView
. Copie e cole o código a seguir, que adiciona um novo estado chamado zoomInCenter
. Ele também modifica a visualização usando clipShape
e varia o diâmetro da forma cortada, dependendo do 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))
}
}
}
}
- Execute o app para ver os resultados.
9. Enviar um evento para o SwiftUI
Nesta etapa, você irá detectar eventos emitidos pela visualização GMSMapView
e enviá-los para o SwiftUI. Mais especificamente, você irá definir um delegado para a visualização de mapa e detectar eventos de movimento da câmera. Dessa forma, quando uma cidade estiver focada e a câmera do mapa se mover devido a um gesto, a visualização de mapa será desfocada, exibindo uma parte maior do mapa.
Como usar os coordenadores do SwiftUI
A GMSMapView
emite eventos como mudanças na posição da câmera ou a seleção de um marcador. Esses eventos são detectados pelo protocolo GMSMapViewDelegate. O SwiftUI introduz o conceito de um coordenador, que é usado especificamente para atuar como delegado dos controladores de visualização do UIKit. Portanto, no SwiftUI, um coordenador precisa ser responsável por estar em conformidade com o protocolo GMSMapViewDelegate
. Para isso, siga as seguintes etapas:
- Crie um coordenador chamado
MapViewCoordinator
dentro doMapViewControllerBridge
.
Crie uma classe aninhada dentro da classe MapViewControllerBridge
e chame-a de MapViewCoordinator
. Essa classe precisa estar em conformidade com o GMSMapViewDelegate
e declarar MapViewControllerBridge
como uma propriedade.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
var mapViewControllerBridge: MapViewControllerBridge
init(_ mapViewControllerBridge: MapViewControllerBridge) {
self.mapViewControllerBridge = mapViewControllerBridge
}
}
}
- Implemente
makeCoordinator()
noMapViewControllerBridge
.
Em seguida, implemente o método makeCoordinator()
dentro do MapViewControllerBridge
e retorne uma instância do MapViewCoodinator
que você criou na etapa anterior.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeCoordinator() -> MapViewCoordinator {
return MapViewCoordinator(self)
}
}
- Defina
MapViewCoordinator
como delegado da visualização de mapa.
Com o coordenador personalizado criado, a próxima etapa é defini-lo como o delegado da visualização de mapa do controlador. Para fazer isso, atualize a inicialização do controlador de visualização em makeUIViewController(context)
. O coordenador criado na etapa anterior poderá ser acessado pelo objeto "Context".
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
// ...
func makeUIViewController(context: Context) -> MapViewController {
let uiViewController = MapViewController()
uiViewController.map.delegate = context.coordinator
return uiViewController
}
- Adicione uma clausura ao
MapViewControllerBridge
para que o evento de movimentação da câmera possa ser propagado para cima.
Como o objetivo é atualizar a visualização com as movimentos da câmera, declare uma nova propriedade de fechamento que aceite um booleano dentro do MapViewControllerBridge
chamado mapViewWillMove
, e invoque essa clausura no método delegado mapView(_, willMove)
dentro do MapViewCoordinator
. Transmita o valor de gesture
para a clausura. Assim, a visualização do SwiftUI só poderá reagir aos eventos de movimento da câmera causados por gestos.
MapViewControllerBridge
struct MapViewControllerBridge: UIViewControllerRepresentable {
var mapViewWillMove: (Bool) -> ()
//...
final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
// ...
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
self.mapViewControllerBridge.mapViewWillMove(gesture)
}
}
}
- Atualize o ContentView para transmitir um valor de
mapWillMove
.
Com a nova clausura declarada no MapViewControllerBridge
, atualize o ContentView
para transmitir um valor para ela. Nessa clausura, alterne o estado zoomInCenter
para false
se o evento de movimento estiver relacionado a um gesto. Isso mostrará o mapa na visualização completa novamente quando ele for movido com um 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
})
// ...
}
}
}
}
- Execute o app para ver as alterações.
10. Parabéns
Parabéns por chegar até aqui! Vimos bastante conteúdo até aqui, e esperamos que essas lições permitam que você crie seu próprio app no SwiftUI usando o SDK do Maps para iOS.
O que você aprendeu
- As diferenças entre SwiftUI e UIKit
- Como fazer uma ponte entre o SwiftUI e o UIKit usando UIViewControllerRepresentable
- Como fazer alterações na visualização de mapa com Estado e Binding
- Como enviar um evento da visualização de mapa para o SwiftUI usando um Coordenador
Qual é a próxima etapa?
- SDK do Maps para iOS: documentação oficial do SDK do Maps para iOS.
- SDK do Places para iOS: encontre empresas locais e pontos de interesse ao seu redor.
- maps-sdk-for-ios-samples: exemplo de código no GitHub que demonstra todos os recursos do SDK do Maps para iOS.
- SwiftUI: documentação oficial da Apple sobre o SwiftUI.
- Ajude-nos a criar o conteúdo mais relevante para você respondendo à pergunta abaixo:
Quais outros codelabs você quer ver?
O codelab que você quer ver não está listado acima? Solicite-o criando um novo "Issue" aqui.