I've got a performance problem regarding adding annotations to maps in iOS (using the standard mapkit methods - hence using Apple maps). I'm trying to add a large number of annotations (10000+) in bulk, using the (void)addAnnotations:(NSArray *)annotations
method. The annotation objects are nothing special - a very basic class that implements MKAnnotation
with only the constructor defined as follows:
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d {
if(self = [super init]) {
title = ttl;
coordinate = c2d;
}
return self;
}
In order to test, I've created a basic app that simply adds the annotations to a basic map view on load, and it takes around 6-7 seconds on an iPad 2. Very acceptable performance. However, things get complicated when I embed the same basic map view in my own application. It's the exact same logic, but when I do it in my app, it takes around 50 seconds to load all the annotations.
My app has a bunch of views within each other. To pinpoint the problem, I've started embedding the map view starting from the lowest level, until I reach the top level. I've done profiling in each step to see if it helps the performance, but I don't see any results - it's still around 50 seconds. Right now, my app basically just loads and adds the annotations to the top and only level map view, ideally the same as the standalone app, but for whatever reason, I still see the annotation rendering taking around 50 seconds. The only reasonable explanation I have is in regards to some of the app settings I have that somehow interferes with the map performance. I've done a bunch of reading to come up with a solution to no avail.
Anyone have any ideas about what might be the problem here? Thanks!
There is no actual "problem". I mean, you have more than 10000 allocations, draws and renderings that are actually having impact on the performance of the application.
My suggestion is to intercept the user navigation on the map. Use something like [mapView visibleMapRect]
to get the visible portion of the map on the screen. Get the coordinates of the rect (maybe a little bit bigger so that cannot be noticed by the user when moving the map) and load only the annotations within that rect.
As the user moves, you only have to load the annotations that are within the new rect MINUS the annotations that were already loaded in the previous rect. I guess you can also remove the annotation when they go out of the screen.
This resembles a little bit what Apple suggests to do when dealing with scrolling views. I remember the application in which the user would have to load the content of the previous and next section of the scrollview (and to release the content of the previous-1 view) so to have a slow memory consumption and still maintaining a good user experience.
Try to think about what the user is looking at, try to show only the annotations that matter that portion (or region as they are called in the MKMapView jargon) and I think your app responsiveness will just improve right away.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With