In the last few months I have been working more intensively with MapKit
, doing more advanced operations like clustering map annotations or animating annotation position changes.
I have encountered a few problem resulting in MKMapView
quite unexpectedly crashing the whole application that I had to fix, or maybe better to say, work around.
MKMapView crashing the view controller on dismiss
During the application testing I noticed a very strange bug. Sometimes when I dismissed the view controller with MKMapView
the application just crashed.
Debugging I noticed that it happened when the annotations on the map were updated just a short while before dismissing the view controller and the crash log pointed to mapView(_:viewFor:)
.
I guessed that MKMapView
was processing annotation changes when the view controller was already deallocated
. The MKMapView
was still alive, tried to call its delegate, which was that deallocated view controller, and crashed.
The fix for this problem was setting the MKMapView
’s delegate to nil
in the view controller’s deinit
method.
deinit {
mapView.delegate = nil
}
Crashing when animating annotation position changes
The second crash I encountered was a bit more tricky. The application started crashing when I implemented animating the annotation position changes.
The way this works is you have a collection of your annotation objects, each has a coordinate
property that needs to be @objc dynamic
because MKMapView
uses KVO to observe it. When you update this property the annotation changes its position on the map.
If you want to animate the position change on the map, you need to wrap the coordinate
property assignment into UIView.animate
. Doing this the application started crashing when the user moved the map, or zoomed it, or sometimes just after a while with the user not doing anything a all
The exception said
Collection was mutated while being enumerated.
but the annotation collection was not really mutated as a whole, some annotation in that collection was mutated by updating its coordinate
property.
Theory about the crash
The circumstances of the crash led me to believe that there was some timing issue, my code updating the annotation at the same the MKMapView
processes it in some way.
Which would make sense, when the user moves the map or zooms it there might be some processing needed to bring annotations into view or hide them.
The interesting thing was this only happened when using annotation clustering. It never happened with “plain” annotations.
With this observation it looked like MKMapView
trying to recompute the clusters causing the crash.
[Read More]