All changes require minimal code changes and boost perfomance substantially. This is not a tutorial on how to use a map view.
Dequeue
If you are looking at this blog, there is a high chance you already know the following optimization.
Map Views are set up very similary to Table Views from an interface perspective. Developers should make sure they dequeue MKMapAnnotations.
|
|
This simple change lets the map view reuse annotation views when they move offscreen. The perfomance gained from this system is crucial for keeping the map scrolling smoothly when there are large quantities of annotations. As a tradeoff, this optimization will increase the memory used, but it is generally considered best practice.
Annotation Callouts
Typically, developers choose to add callout accessory views inside mapView(viewFor:), however this is actually a critical memory mistake since accesssory view creation is not lazy
. Unless there is some special reason you need to create your accessory view inside mapView(viewFor:), you should instead create it in mapView(didSelect:).
|
|
Clustering Annotation Views
Clustering annotation views is a great way of reducing the number of annotations being rendered on screen - it should be used in almost all scenarios. Benifits from this optimization greatly outweigh the previous two optimizations in most scenarios. There are many great tutorials on clustering, so I won’t dive into it in this post.
Caching User Location
Unless you need real time updating information, you should not be using mapView.showsUserLocation = true
, because it consumes a lot of energy continuously (in my tests it was consuming ~10% of CPU.)
Instead, cache a pin and update it’s location manually.
|
|
Devices iOS 14+ are compatible with a manually placed “default” user location pin - devices bellow iOS 14 are stuck with whatever you come up with.
|
|
Getting Memory to Release
The biggest problem with map views is that they never release their memory. Apps using map views will often balloon to hundreds of mb of memory within a few scrolls. This memory will then refuse to be released, damaging the performance of the rest of the app/device. Unfortunatly there is no mapView.clearCache()
function, so we will have to do it ourselves.
The solution is to create the map view programmatically, and delete/recreate when necessary. This optimization is highly application specific, so I leave it to the reader.