Animating location changes of an annotation in UIKit and MKMapView
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
})
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.