Aula 106: Integrando MapKit com SwiftUI
Nesta aula, vamos explorar como integrar o MapKit com o SwiftUI, permitindo exibir mapas e dados de localização em nossas aplicações Swift. Vamos passar pelo processo de criação de um aplicativo simples que mostra um mapa centrado em uma localização específica, lida com a localização do usuário e adiciona anotações.
Configurando Seu Projeto
- Abra o Xcode e crie um novo projeto SwiftUI.
- Certifique-se de que você habilitou o framework MapKit. Você pode fazer isso navegando até as configurações do seu projeto, selecionando a aba "General", descendo até "Frameworks, Libraries, and Embedded Content" e adicionando o MapKit.
Importando Módulos Necessários
No topo do seu arquivo ContentView.swift
, certifique-se de importar tanto o SwiftUI quanto o MapKit:
import SwiftUI
import MapKit
Criando uma Vista de Mapa
Vamos criar uma vista de mapa básica envolta em uma vista SwiftUI
. Comece criando uma nova struct chamada MapView
.
struct MapView: UIViewRepresentable {
@Binding var region: MKCoordinateRegion
func makeUIView(context: Context) -> MKMapView {
MKMapView()
}
func updateUIView(_ uiView: MKMapView, context: Context) {
uiView.setRegion(region, animated: true)
}
}
Explicação
- A
MapView
conforma-se aUIViewRepresentable
, permitindo que usemos visões UIKit em nosso layout SwiftUI. - Usamos uma propriedade
Binding
pararegion
para tornar o mapa responsivo às mudanças no estado do SwiftUI.
Adicionando a Localização do Usuário
A seguir, vamos modificar nosso ContentView
para incluir o rastreamento da localização do usuário:
struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.773972, longitude: -122.431297), // São Francisco
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
var body: some View {
MapView(region: $region)
.edgesIgnoringSafeArea(.all)
.onAppear {
// Solicitar a localização do usuário
verificarSeOsServiçosDeLocalizaçãoEstãoHabilitados()
}
}
private func verificarSeOsServiçosDeLocalizaçãoEstãoHabilitados() {
if CLLocationManager.locationServicesEnabled() {
// Definir a região para a localização do usuário
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
locationManager.startUpdatingLocation()
}
}
}
extension ContentView: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else { return }
region.center = location.coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Falha ao encontrar a localização do usuário: \(error.localizedDescription)")
}
}
Explicação
- Definimos uma propriedade
@State
para aregion
do mapa, para que ela possa ser modificada quando a localização do usuário mudar. - A função
verificarSeOsServiçosDeLocalizaçãoEstãoHabilitados
verifica e solicita permissões de localização. - Ao conformar-se com o
CLLocationManagerDelegate
, podemos atualizar a região do mapa com a localização atual do usuário.
Adicionando Anotações
Para aprimorar nosso mapa, adicionaremos uma anotação para uma localização específica. Vamos modificar a MapView
para aceitar anotações:
struct MapView: UIViewRepresentable {
@Binding var region: MKCoordinateRegion
var annotations: [MKPointAnnotation]
func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
return mapView
}
func updateUIView(_ uiView: MKMapView, context: Context) {
uiView.setRegion(region, animated: true)
// Remover anotações existentes
uiView.removeAnnotations(uiView.annotations)
// Adicionar novas anotações
uiView.addAnnotations(annotations)
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, MKMapViewDelegate {
var parent: MapView
init(_ parent: MapView) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "MinhaAnotação"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
return annotationView
}
}
}
Explicação
- Adicionamos uma propriedade para
annotations
para armazenar os pins do mapa. - A classe
Coordinator
gerencia a criação e configuração da vista de anotação. - Atualizamos a vista do mapa para remover anotações existentes antes de adicionar novas.
Atualizando a View de Conteúdo com Anotações
Por fim, vamos atualizar o ContentView
para incluir as anotações:
struct ContentView: View {
@State private var region = MKCoordinateRegion(
center: CLLocationCoordinate2D(latitude: 37.773972, longitude: -122.431297),
span: MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
)
private var annotations: [MKPointAnnotation] {
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: 37.773972, longitude: -122.431297)
annotation.title = "São Francisco"
return [annotation]
}
var body: some View {
MapView(region: $region, annotations: annotations)
.edgesIgnoringSafeArea(.all)
.onAppear {
verificarSeOsServiçosDeLocalizaçãoEstãoHabilitados()
}
}
private func verificarSeOsServiçosDeLocalizaçãoEstãoHabilitados() {
if CLLocationManager.locationServicesEnabled() {
let locationManager = CLLocationManager()
locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
locationManager.startUpdatingLocation()
}
}
}
extension ContentView: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else { return }
region.center = location.coordinate
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Falha ao encontrar a localização do usuário: \(error.localizedDescription)")
}
}
Explicação
- Definimos
annotations
como uma propriedade computada que cria um pin para São Francisco. - A
MapView
é atualizada para receber e exibir essas anotações no mapa.
Conclusão
Nesta aula, aprendemos como integrar o MapKit com o SwiftUI, permitindo que criemos uma interface de mapa em nossas aplicações. Abordamos como gerenciar a localização do usuário e adicionar anotações ao mapa. Isso forma a base para funcionalidades mais avançadas, como exibir múltiplas anotações ou integrar com serviços de localização para diversos recursos.
Sinta-se à vontade para experimentar com diferentes locais de mapa, anotações ou até mesmo integrar interações mais complexas à medida que você se familiariza mais com o MapKit e o SwiftUI. Feliz codificação!