MKPointAnnotation - sKarumba/TourApp GitHub Wiki

#MKPointAnnotation Tutorial

The MKPointAnnotation is the basic version of an annotation that can be used to display a pin along with a title and subtitle. If you want to do more than show a point on a map with a title, then you will need to use MKAnnotation and MKAnnotationView.

##Creating the MKPointAnnotation

We first start by creating an MKPointAnnotation pointer as follows:

MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc]init];

Next, we need to configure the annotation. It needs three things to work. First we need to provide a coordinate of where to drop the pin. We then need to supply a title (if needed) and finally, we need to specify a subtitle.

CLLocationCoordinate2D pinCoordinate;
pinCoordinate.latitude = 51.49795;
pinCoordinate.longitude = -0.174056;
myAnnotation.coordinate = pinCoordinate;

On line 1 we create a CLLocationCoordinate2D called pinCoordinate. A CLLocationCoordinate2D is a struct which contains both a latitude and a longitude.

On lines 2 and 3 we specify the pinCoordinate.latitude and then the pinCoordinate.longitude.

On line 4, we access the coordinate property of our MKPointAnnotation and assign it the pinCoordinate.

We can cut all of this down to just a single line of code as follows:

myAnnotation.coordinate = CLLocationCoordinate2DMake(51.49795, -0.174056);

We next need to go ahead and add a title and subtitle. The code so far looks like this:

myAnnotation.title = @"Matthews Pizza";
myAnnotation.subtitle = @"Best Pizza in Town";

Finally, we need to add the annotation to the map. We do that with the following line of code:

[self.mapView addAnnotation:myAnnotation];

##Changing the Pin Colour or Pin Image

Although MKPointAnnotation is basic and can only provide a coordinate, name and subtitle, you can still use this class when customising the pin. Lets look at the code to do this:

What we do next is override the – (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation method from the delegate which lets us customise the view.

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
    // If it's the user location, just return nil.
    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    // Handle any custom annotations.
    if ([annotation isKindOfClass:[MKPointAnnotation class]])
    {
        // Try to dequeue an existing pin view first.
        MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
        if (!pinView)
        {
            // If an existing pin view was not available, create one.
            pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];
            //pinView.animatesDrop = YES;
            pinView.canShowCallout = YES;
            pinView.image = [UIImage imageNamed:@"pizza_slice_32.png"];
            pinView.calloutOffset = CGPointMake(0, 32);
        } else {
            pinView.annotation = annotation;
        }
        return pinView;
    }
    return nil;
}

To change the pin colour, modify the code as follows:

MKPinAnnotationView *pinView = (MKPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
        if (!pinView)
        {
            // If an existing pin view was not available, create one.
            pinView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];
            //pinView.animatesDrop = YES;
            pinView.canShowCallout = YES;
            //pinView.image = [UIImage imageNamed:@"pizza_slice_32.png"];
            pinView.pinColor = MKPinAnnotationColorPurple;

##Adding Left and Right Callouts to Further Enhance the Annotation Details

With the MKPointAnnotation we can also enhance use the MKAnnotationView to add a left and right callout. In this example we’ll put the disclosure button on the right and a thumbnail on the left. We do this as follows:

// Add a detail disclosure button to the callout. UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; pinView.rightCalloutAccessoryView = rightButton;

// Add an image to the left callout.
UIImageView *iconView = [UIImageView alloc] initWithImage:[UIImage imageNamed:@"pizza_slice_32.png"](/sKarumba/TourApp/wiki/UIImageView-alloc]-initWithImage:[UIImage-imageNamed:@"pizza_slice_32.png");
pinView.leftCalloutAccessoryView = iconView;

To get the disclosure button working we need to override the delegate method called mapView:annotationView:calloutAccessoryControlTapped:

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
    id <MKAnnotation> annotation = [view annotation];
    if ([annotation isKindOfClass:[MKPointAnnotation class]])
    {
        NSLog(@"Clicked Pizza Shop");
    }
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Disclosure Pressed" message:@"Click Cancel to Go Back" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
    [alertView show];
} 

The full code for this project is listed below.

###Header Code

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController <MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;

@end

###Implementation Code

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.mapView.delegate = self;
    self.mapView.mapType = MKMapTypeStandard;
    self.mapView.showsUserLocation = YES;

    MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
    myAnnotation.coordinate = CLLocationCoordinate2DMake(51.49795, -0.174056);
    myAnnotation.title = @"Matthews Pizza";
    myAnnotation.subtitle = @"Best Pizza in Town";
    [self.mapView addAnnotation:myAnnotation];
}

#pragma mark Delegate Methods

-(void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
id <MKAnnotation> annotation = [view annotation];
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
    NSLog(@"Clicked Pizza Shop");
}
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Disclosure Pressed" message:@"Click Cancel to Go Back" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
[alertView show];
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation

{ // If it's the user location, just return nil. if ([annotation isKindOfClass:[MKUserLocation class]]) return nil;

// Handle any custom annotations.
if ([annotation isKindOfClass:[MKPointAnnotation class]])
{
    // Try to dequeue an existing pin view first.
    MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"];
    if (!pinView)
    {
        // If an existing pin view was not available, create one.
        pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomPinAnnotationView"];
        pinView.canShowCallout = YES;
        pinView.image = [UIImage imageNamed:@"pizza_slice_32.png"];
        pinView.calloutOffset = CGPointMake(0, 32);
        
        // Add a detail disclosure button to the callout.
        UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        pinView.rightCalloutAccessoryView = rightButton;
        
        // Add an image to the left callout.
        UIImageView *iconView = [UIImageView alloc] initWithImage:[UIImage imageNamed:@"pizza_slice_32.png"](/sKarumba/TourApp/wiki/UIImageView-alloc]-initWithImage:[UIImage-imageNamed:@"pizza_slice_32.png");
        pinView.leftCalloutAccessoryView = iconView;
    } else {
        pinView.annotation = annotation;
    }
    return pinView;
}
return nil;
}

#pragma mark Zoom

- (IBAction)zoomToCurrentLocation:(UIBarButtonItem *)sender {
float spanX = 0.00725;
float spanY = 0.00725;
MKCoordinateRegion region;
region.center.latitude = self.mapView.userLocation.coordinate.latitude;
region.center.longitude = self.mapView.userLocation.coordinate.longitude;
region.span.latitudeDelta = spanX;
region.span.longitudeDelta = spanY;
[self.mapView setRegion:region animated:YES];
}

#pragma mark Memory Warning

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end