inertiaBlogs()

Animating location changes of an annotation in UIKit and MKMapView

· Jimin Lee

In one of my personal projects, I needed to use a custom annotation as a location marker rather than using the default location marker as the user’s location was determined by a network of Bluetooth iBeacons rather than using the native Core Location framework.

But when I tried to update the position of an annotation by changing its coordinate attribute, it flashed to the new location rather than being animated to that location.

After doing some research I found out that you have to mark the coordinate attribute in your MKAnnotation class as @objc dynamic var like

final class CustomAnnotation: NSObject, MKAnnotation {
    @objc dynamic var coordinate: CLLocationCoordinate2D
    init(coordinate: CLLocationCoordinate2D) {
        self.coordinate = coordinate
        super.init()
    }
}

and wrap it around a UIView.animate function like

UIView.animate(withDuration: 0.3, animations: {
  annotation.coordinate = anyCoordinate
})
However this still didn’t animate my location change when changing the coordinate attribute.

It turns out that if you want the coordinate change to be animated in the simulator, the coordinate change has to be run from the main thread

DispatchQueue.main.async {
            UIView.animate(withDuration: 0.3, animations: {
              annotation.coordinate = anyCoordinate
            })
}

But when I ran it on a real iPhone, the coordinate change still wasn’t animated.

To have the coordinate change of your custom annotation animated by SwiftUI/UIKit on a real iOS device you need to remove the queue onto main thread line and revert back to

UIView.animate(withDuration: 0.3, animations: {
  annotation.coordinate = anyCoordinate
})

Since most apps are developed with the intention of it being run on a real iOS device, I suggest implementing coordinate changes without wrapping it in the DispatchQueue function.