TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

Update MapView with current location on SwiftUI

Forums > SwiftUI

Trying to update the mapview of the Project 14 of 100daysOfSwiftUI to show my current location, the problem i can´t zoom in move around

i have this code i add @Binding var currentLocation : CLLocationCoordinate2D and view.setCenter(currentLocation, animated: true to my MapView so i have a button that send thats value and the view actually move so slow to the location but then i can move away anymore

import SwiftUI
import MapKit

struct MapView: UIViewRepresentable {

    @Binding var centerCoordinate: CLLocationCoordinate2D
    @Binding var selectedPlace: MKPointAnnotation?
    @Binding var showingPlaceDetails: Bool
    @Binding var currentLocation : CLLocationCoordinate2D

    var annotations: [MKPointAnnotation]

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        return mapView
    }

    func updateUIView(_ view: MKMapView, context: Context) {

        if annotations.count != view.annotations.count {
            view.removeAnnotations(view.annotations)
            view.addAnnotations(annotations)
        }

        view.setCenter(currentLocation, animated: true)

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

 class Coordinator: NSObject, MKMapViewDelegate{

    var parent: MapView
    init(_ parent: MapView) {
        self.parent = parent
    }

    func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
         parent.centerCoordinate = mapView.centerCoordinate
     }

     func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
         let identifier = "PlaceMark"
         var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
         if annotationView == nil {
             annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
             annotationView?.canShowCallout = true
             annotationView?.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)

         } else {
             annotationView?.annotation = annotation
         }

         return annotationView
     }

     func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
         guard let placemark = view.annotation as? MKPointAnnotation else {return}
         parent.selectedPlace = placemark
         parent.showingPlaceDetails = true

     }

    }
}

an this is my swiftUI view

...
    @State private var currentLocation = CLLocationCoordinate2D()

    var body: some View {
        ZStack{

            MapView(centerCoordinate: $centerCoordinate, selectedPlace: $selectedPlace, showingPlaceDetails: $showingPlaceDetails, currentLocation: $currentLocation ,  annotations: locations)
           // MapView(centerCoordinate: $centerCoordinate, selectedPlace: $selectedPlace, showingPlaceDetails: $showingPlaceDetails, annotations: locations)
                .edgesIgnoringSafeArea(.all)
            VStack{
                Spacer()
                HStack{
                    Spacer()
                    Button(action: {
                        self.getCurrentLocation()
                    }){
                        ButtonIcon(icon: "location.fill")
                    }
                }
                .padding()
            }
        }
        .onAppear(perform: getCurrentLocation)
    }

    func getCurrentLocation() {

        let lat = locationManager.lastLocation?.coordinate.latitude ?? 0
        let log = locationManager.lastLocation?.coordinate.longitude ?? 0

        self.currentLocation.latitude = lat
        self.currentLocation.longitude = log

    }
    ...

i just want to center my mapview on my current location when i press the laction button

2      

@misaellandero

Since call to this method view.setCenter(currentLocation, animated: true) will result in change of region on map, this will in turn trigger MKMapView delegate method mapViewDidChangeVisibleRegion(_ mapView: MKMapView) here, we are updating centerCoordinate which is not required. I think now you understand the reason behind slow transition to currentLocation.

I except this solution would work for you:

Step 1: add this line mapView.showsUserLocation = false inside makeUIView(context: Context) -> MKMapView like this:

func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView()
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = false // I know this is default but, it improve readability
        return mapView
    }

Step 2: Set this property to true as shown below

func updateUIView(_ view: MKMapView, context: Context) {

        if annotations.count != view.annotations.count {
            view.removeAnnotations(view.annotations)
            view.addAnnotations(annotations)
        }
        view.showsUserLocation = true
        view.setCenter(currentLocation, animated: true)

    }

Step 3: Use this property to avoid unnecessary update for centerCoordinate as follows

func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
          if !mapView.showsUserLocation {
               parent.centerCoordinate = mapView.centerCoordinate
         }
     }

That's it, this is how I resloved my issue, hope this helps.

If you are curious here is the link of my project, Complete Challenge

2      

Hacking with Swift is sponsored by String Catalog.

SPONSORED Get accurate app localizations in minutes using AI. Choose your languages & receive translations for 40+ markets!

Localize My App

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.