Search code examples
iosswiftmapkitmkmapview

How to Update Annotation Coordinates on MapView


I have a mapView and vehicle coordinates which changes in every 15 seconds so I want to update the coordinates. My current approach is to delete all annotations and adding new ones. However, I can't use animations in that approach, they are just spawning. When I looked google I've found out that people just changing the coordinates of annotations and it's happening. Not for me unfortunately.

Old version:

 func updateVehicleLocations(){
        let annotations = mapView.annotations.filter {
            $0.title != "person"
        }
        mapView.removeAnnotations(annotations)
        
        for vehicle in vehicles {
            let pin = MKPointAnnotation()
            pin.coordinate = CLLocationCoordinate2D(latitude: vehicle.latitude, longitude: vehicle.longitude)
            pin.title = vehicle.vehicleID
            mapView.addAnnotation(pin)
        }
        
        if isSetCoordinatesMoreThanOnce { return }
        mapView.showAnnotations(mapView.annotations, animated: true)
        isSetCoordinatesMoreThanOnce = true
    }

My test:

func updateVehicleLocations(){
        for annotation in busAnnotations {
            UIView.animate(withDuration: 0.5) { [self] in
                if let vehicle = self.vehicles.first(where: { $0.vehicleID == annotation.vehicleID }) {
                    annotation.coordinate = CLLocationCoordinate2D(latitude: vehicle.latitude, longitude: vehicle.longitude)
                }
            }
        }

       if isSetCoordinatesMoreThanOnce { return }
        
        for vehicle in vehicles {
            let pin = BusAnnotation(coordinate: CLLocationCoordinate2D(latitude: vehicle.latitude, longitude: vehicle.longitude), vehicleID: vehicle.vehicleID)
            busAnnotations.append(pin)
        }
        
        mapView.addAnnotations(busAnnotations)
        mapView.showAnnotations(mapView.annotations, animated: true)
        isSetCoordinatesMoreThanOnce = true
    }

Solution

  • That was exhausting, I still don't get the logic but here is how I fixed it;

    I had to use a custom class(of MKAnnotation) to set coordinates otherwise the coordinate property is read-only. So, here is an example custom annotation class;

        final class BusAnnotation: NSObject, MKAnnotation{
        var vehicleID: String
        var coordinate: CLLocationCoordinate2D
        init(coordinate: CLLocationCoordinate2D, vehicleID:String) {
            self.coordinate = coordinate
            self.vehicleID = vehicleID
            super.init()
        }
    }
    

    however, it doesn't update coordinates, to fix it we need to add "dynamic" keyword to coordinate property everything works fine!

        final class BusAnnotation: NSObject, MKAnnotation{
        var vehicleID: String
        dynamic var coordinate: CLLocationCoordinate2D
        init(coordinate: CLLocationCoordinate2D, vehicleID:String) {
            self.coordinate = coordinate
            self.vehicleID = vehicleID
            super.init()
        }
    }