Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toubleshooting mapkit performance

I'm plotting over 500 points on a map using mapkit. Zooming is a little jittery compared to the native google map app. I've discovered what is causing the slowness. I'm adding custom annotations so that I can later add different pin colors and buttons for detail views:

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(AddressNote *) annotation {
    MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentlocation"];
    annView.pinColor = MKPinAnnotationColorGreen;
    annView.animatesDrop=TRUE;
    annView.canShowCallout = YES;
    annView.calloutOffset = CGPointMake(-5, 5);
    return annView;
}

If I comment out the above code, everything works fine. Very smooth with zooming in/out. Should I be adding annotations differently to boost performance?

like image 665
user230949 Avatar asked Feb 08 '10 02:02

user230949


People also ask

What is the main purpose of MapKit framework?

Overview. Use MapKit to give your app a sense of place with maps and location information. You can use the MapKit framework to: Embed maps directly into your app's windows and views.

What is MapKit span?

The "span" in this class refers to the width and height of a region, with distances expressed in degrees of latitude and longitude.

What is MapKit framework in iOS?

MapKit is a powerful API available on iOS devices that makes it easy to display maps, mark locations, enhance with custom data and even draw routes or other shapes on top.


4 Answers

500 annotations is probably too many, but not so many that the performance suffers when you are only viewing some of them. However, you should be using dequeueing with your annotations to improve performance

- (MKAnnotationView *)mapView:(MKMapView *)mapView
            viewForAnnotation:(id <MKAnnotation>)annotation
{
    MKPinAnnotationView *view = nil;
    if (annotation != mapView.userLocation) {
        view = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"identifier"];
        if (nil == view) {
            view = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"identifier"] autorelease];
        }
        [view setPinColor:MKPinAnnotationColorGreen];
        [view setCanShowCallout:YES];
        [view setAnimatesDrop:NO];
    }
    else {
        // Do something with the user location view
    }
    return view;
}

Also, with 500 pins, the drop animation takes a long time to finish. You should turn that off with [view setAnimatesDrop:NO]

like image 190
nevan king Avatar answered Sep 19 '22 05:09

nevan king


I wrote an iPhone app for a client and we included a store locator for one of their store brands. It includes 501 locations and while the animation can be a bit jerky when you are zoomed out to view the entire United States, it's perfectly fine zoomed in to the state level, where only a handful of pins are visible.

The keys:

  • Zoom the user into their current location before you add your annotations.
  • Reuse annotation views using dequeueReusableAnnotationViewWithIdentifier:.

To achieve the first point, you need to turn on location updates and set a flag when you receive the first one. Animate the map to that location using a region span that makes sense for your app, then in mapView:regionDidChangeAnimated:, check to see if you still need to add your annotations and that the current location has been updated before you call addAnnotation:.

If you can't or don't want to zoom in to the user's location, can you filter the annotations shown at the highest level and only add additional annotations as the user zooms in?

By the way, I believe you have a memory leak in your code as posted above. Even if you don't want to use the dequeuing mechanism, the view you return from mapView:viewForAnnotation: should be autoreleased.

like image 27
Steve Madsen Avatar answered Sep 18 '22 05:09

Steve Madsen


I think St3fan is correct. In theory you can just keep adding annotations to the map and let the view handle display of them, but the reality is that it's better if you keep the count down a bit, 500 on screen at once would be way too many to see anyway.

However there is one more step to try - make sure all of the annotation views have opaque set to YES like so:

annView.opaque = YES; 
like image 22
Kendall Helmstetter Gelner Avatar answered Sep 19 '22 05:09

Kendall Helmstetter Gelner


It sounds to me that adding 500 map points to a section of a map the size of the iPhone screen makes no sense. There is no way you can visualize that or even click on the right annotation.

Can't you look at the zoom level and center of the map and then decide to only add a subset of annotations to the map?

I think I've seen other apps do this too.

like image 20
Stefan Arentz Avatar answered Sep 21 '22 05:09

Stefan Arentz