Search code examples
iosxcodeannotationsmapkitmkannotationview

How to add an image for each customized annotation on MapView?


I have a class of Picture which contains latitude and longitude and image of each location. I want to add them as annotation to the MapView and show its image instead of pin for those locations.

I have a customized annotation which is:

@interface Annotation : MKAnnotationView  <MKAnnotation>

@property (nonatomic,assign) CLLocationCoordinate2D coordinate;
@property (nonatomic,copy) NSString *title;
@property (nonatomic,copy) NSString *subtitle;
@property (nonatomic,retain) UIImage *image;


@end

And

@implementation Annotation 

@synthesize title,subtitle,coordinate,image;


@end

Now in main code I am trying this:

CLLocationCoordinate2D location;
Annotation *myAnn;

for(Pictures *pic in picturesFromDB)
{
myAnn = [[Annotation alloc] init];
location.latitude = [pic.langT doubleValue];
location.longitude = [pic.longT doubleValue];
myAnn.coordinate = location;
myAnn.title = pic.descript;


myAnn.image = [UIImage imageWithData:pic.image]; //Not sure about this line!


[self.mapView addAnnotation:myAnn];

}

Do I still need the delegate and must call "viewForAnnotation"? Because it did not work, I did this for delegate:

- (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:[Annotation 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:@"image.png"];            
            pinView.calloutOffset = CGPointMake(0, 4);

        } else {

            pinView.annotation = annotation;
        }
        return pinView;
    }
    return nil;
}

This is working fine but adding same image to all the locations. But I have a specific image to show instead of image.png above for each location.

Number of location is variable and also dynamic.

How can I pass that image to the delegate. I tried to find the image field in the passed annotation, but it does not exist! I appreciate any suggestion.


Solution

  • You need to cast the annotation to your custom class so that you can access its properties -

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
    {
    
        // Handle any custom annotations.
        if ([annotation isKindOfClass:[Annotation class]])
        {
            Annotation *myAnn=(Annotation *)annotation;
            // 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.calloutOffset = CGPointMake(0, 4);
    
            } else {
                pinView.annotation = annotation;
            }
            pinView.image = myAnn.image;
            return pinView;
        }
        return nil;
    }