I have a modal view in my app which displays a UIMapView. I then add a large number of annotations (over 800) to this map view (code below).
The problem is that the
I completely agree with Anna. But consider that 800 AnnotationViews at the same time will result in a extreme laggy interface. So if your map should provide user interaction like scrolling or zooming you better implement some kind clustering of your annotation views.
The two biggest speed improvements you can make here are:
UniqueID
is set. To set it, the code is currently looping through all the annotations every time it creates an annotation view (which could happen any time the map view is zoomed or scrolled--not just the initial time).First, instead of searching for the UniqueID
in the viewForAnnotation
method and using a button tag to pass the annotation identifier, add UniqueID
as a property to your custom annotation class MyLocation
and set the property when you add the annotation itself in addPins
:
annotation.uniqueID = info.UniqueID; // <-- give id to annotation itself
[mapViewLink addAnnotation:annotation];
You could also add uniqueID
as a parameter to the initWithName
method instead of assigning the property separately.
Next, to implement annotation view re-use, the viewForAnnotation
method should look like this:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
if (annotation == mapView.userLocation){
return nil; //default to blue dot
}
NSString *reuseId = @"StandardPin";
MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (annView == nil)
{
annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease];
annView.pinColor = MKPinAnnotationColorRed;
annView.animatesDrop = YES;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
advertButton.frame = CGRectMake(0, 0, 23, 23);
advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
annView.rightCalloutAccessoryView = advertButton;
}
else
{
//update the annotation property if view is being re-used...
annView.annotation = annotation;
}
return annView;
}
Finally, to respond to the button press and figure out which UniqueID
to show the detail for, implement the calloutAccessoryControlTapped
delegate method:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control
{
MyLocation *myLoc = (MyLocation *)view.annotation;
int uniqueID = myLoc.uniqueID;
NSLog(@"calloutAccessoryControlTapped, uid = %d", uniqueID);
//create, init, and show the detail view controller here...
}
After all these changes, only the initial loading of the annotations will take up most of the time. If that is still a problem, one solution is to only add annotations that would be visible in the currently displayed region and add/remove annotations as the user changes the visible region.