iOS Map

iOS Map viewer: MKMapView

  • Create with the Interface Builder, or
  • alloc/init
@property (readonly) id <MKAnnotation> annotations;

Map Annotation

Annotation, like pin annotation, can be added to a map to mark locations on a map

  • MKAnnotation is a protocol containing location & title information
  • Application can add an array of objects implementing MKAnnotation to a map view so it can mark it on a map

Declare an Object implement the MKAnnotation Protocol

@interface MyObject <MKAnnotation>
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
@property (readonly) NSString *title;

Implement the MKAnnotation protocol

- (CLLocationCoordinate2D)coordinate
  CLLocationCoordinate2D location;
  location.latitude = ...
  location.longitude = ...
  return location;

- (NSString *)title

To add an array of annotation objects to a map view

[self.mapView addAnnotations:...];

Map Annotation Properties and API


@protocol MKAnnotation <NSObject>
@property (readonly) CLLocationCoordinate2D coordinate;
@property (readonly) NSString *title;
@property (readonly) NSString *subtitle;
typedef {
    CLLocationDegrees latitude;
    CLLocationDegrees longitude;
} CLLocationCoordinate2D;

APIs in adding/removing Map annotation

- (void)addAnnotation:(id <MKAnnotation>)annotation;
- (void)addAnnotations:(NSArray *)annotations;
- (void)removeAnnotation:(id <MKAnnotation>)annotation;
- (void)removeAnnotations:(NSArray *)annotations;

iOS Map Annotation View: MKAnnotationView

When user click on the annotation, an annotation view pops up

  • Create a right and left callout accessor
    - (MKAnnotationView *)mapView:(MKMapView *)sender viewForAnnotation:(id <MKAnnotation>)annotation
      MKAnnotationView *aView = [sender dequeueReusableAnnotationViewWithIdentifier:@"MyAnnotationView"];
      if (!aView) {
        aView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"MyAnnotationView"];
        aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        aView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,30,30)];
        aView.canShowCallout = YES;
      ((UIImageView *)aView.leftCalloutAccessoryView).image = nil;
      aView.annotation = annotation;
      return aView;

Create and download an thumbnail image for the left accessory

- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView
  MyClass o1 = nil;
  UIImageView imageView = nil;
  if ([aView.annotation isKindOfClass:[MyClass class]]) {
    o1 = (MyClass *)aView.annotation;
  if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
    imageView = (UIImageView *)aView.leftCalloutAccessoryView;
  if (o1 && imageView)
    NSString *thumbnailURL = o1.thumbnailURL;
    if (thumbnailURL) {
      dispatch_queue_t downloader = dispatch_queue_create("image downloader", NULL);
      dispatch_async(downloader, ^{
	   UIImage *image = [UIImage imageWithData:[FlickrFetcher imageDataForPhotoWithURLString:thumbnailURL]];
	   dispatch_async(dispatch_get_main_queue(), ^{
		imageView.image = image;

Delegate handle the tapping of the annotation view accessor

- (void)mapView:(MKMapView *)sender annotationView:(MKAnnotationView *)aView calloutAccessoryControlTapped:(UIControl *)control

Annotation Properties

- (void)mapView:(MKMapView *)sender
               annotationView:(MKAnnotationView *)aView
calloutAccessoryControlTapped:(UIControl *)control;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

Delegate for MKMapView

Call when display a map view

- (void)mapView:(MKMapView *)sender regionDidChangeAnimated:(BOOL)animated;

The map rectangle


Only add annotations that is visible in the map

MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
if (MKMapRectContainsPoint(mapView.visibleRect, annotationPoint))
{ ... }