SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
22.11.2024

Lição: 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

  1. Abra o Xcode e crie um novo projeto SwiftUI.
  2. 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 a UIViewRepresentable, permitindo que usemos visões UIKit em nosso layout SwiftUI.
  • Usamos uma propriedade Binding para region 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 a region 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!

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!