2

I have the following files:

annotation.h:

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface annotation : NSObject <MKAnnotation>

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


@end

annotation.m:

#import "annotation.h"

@implementation annotation

@synthesize coordinate, title, subtitle;

@end

And in the main code, which takes in an NSURL found elsewhere:

[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[spinner stopAnimating];

// json parsing
results = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];

NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
annotation * myAnn;

NSArray *pins = mapView.annotations;

if ([pins count])
{
    [mapView removeAnnotations:pins];
}

/* loop through the array, each key in the array has a JSON String with format:
 * title <- string
 * strap <- string
 * id <- int
 * date <- date
 * lat <- floating point double
 * long <- floating point double
 * link <- string

 */
int i;

for (i = 0; i < [results count]; i++) {
    //NSLog(@"Result: %i = %@", i, results[i]);
    //NSLog(@"%@",[[results objectAtIndex:i] objectForKey:@"long"]);

    myAnn = [[annotation alloc] init];
    location.latitude = (double)[[[results objectAtIndex:i] objectForKey:@"lat"] doubleValue];
    location.longitude = (double)[[[results objectAtIndex:i] objectForKey:@"long"] doubleValue];
    myAnn.coordinate = location;
    myAnn.title = [[results objectAtIndex:i] objectForKey:@"title"];
    myAnn.subtitle = [[results objectAtIndex:i] objectForKey:@"strap"];

    [locations addObject:myAnn];

    //NSLog(@"%i", [[results objectAtIndex:i] objectForKey:@"lat"]);
}

[self.mapView addAnnotations:locations];

Previous things I have looked at for this say that I need to use MKAnnotationView as opposed to MKPinAnnotationView but as you can see I do not use either, is it possible for me to use custom images for the pins that are dropped on the screen.

jszumski
  • 7,430
  • 11
  • 40
  • 53
Josh Boothe
  • 1,413
  • 4
  • 25
  • 40

3 Answers3

5

You (a) make sure to define your view controller to be the delegate for your MKMapView; and (b) implement viewForAnnotation, e.g.:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }

    if ([annotation isKindOfClass:[CustomAnnotation class]]) {
        static NSString * const identifier = @"MyCustomAnnotation";
                    
        MKAnnotationView* annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
        
        if (annotationView) {
            annotationView.annotation = annotation;
        } else {
            annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
                                                          reuseIdentifier:identifier];
        }

        // set your annotationView properties
        
        annotationView.image = [UIImage imageNamed:@"Your image here"];
        annotationView.canShowCallout = YES;

        // if you add QuartzCore to your project, you can set shadows for your image, too
        //
        // [annotationView.layer setShadowColor:[UIColor blackColor].CGColor];
        // [annotationView.layer setShadowOpacity:1.0f];
        // [annotationView.layer setShadowRadius:5.0f];
        // [annotationView.layer setShadowOffset:CGSizeMake(0, 0)];
        // [annotationView setBackgroundColor:[UIColor whiteColor]];
        
        return annotationView;
    }

    return nil;
}

By the way, in my example above, I changed the name of your annotation class to CustomAnnotation. annotation is a horrible name for a class because (a) it doesn't follow class naming conventions of upper case first letter; and (b) it's identical to the variable name, annotation, that many MKMapViewDelegate methods will use by default.

References

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Hi Rob, thanks for this answer - I keep seeing similar things except I dont really know where to put it! Is it in the annotations.m file, or rather.. customAnnotation.m file? – Josh Boothe Apr 14 '13 at 18:12
  • @JoshBoothe You put this method in your view controller. Also, don't forget to make sure to set your view controller to be the `delegate` for the mapview (you can either do this in IB, or in your `viewDidLoad` you can have a line that says "`self.mapView.delegate = self;`". You may also want to add a "``" to the end of the `@interface` line for your view controller. See the "Annotating Maps" section of that _Location Awareness Programming Guide._ – Rob Apr 14 '13 at 18:14
  • I think I already have set the delegate? In my FirstViewController.h I have the outlet and `@property (weak, nonatomic) IBOutlet MKMapView *mapView;`. – Josh Boothe Apr 14 '13 at 18:17
  • And your class name is _not_ supposed to be `customAnnotation`, but rather `CustomAnnotation`. Classes start with uppercase letters, variables start with lowercase letters. It's convention (and avoids precisely the sort of confusion to which I alluded in my answer). – Rob Apr 14 '13 at 18:18
  • @JoshBoothe All that `IBOutlet` does is define an outlet that you hopefully hooked up in Interface Builder. I'm saying that in addition to that, you need to _also_ hook up the `delegate` property of your `MKMapView`. You can either do this in code (as I've described above) or better, in Interface Builder, select the `MKMapView` go to your outlets inspector (the last tab of that panel on the right), you'll see the `delegate` property listed there, and drag the link from that to your view controller. – Rob Apr 14 '13 at 18:22
  • Ahh I see thanks! That makes sense, thank you for explaining that to me. I have added the code and changed the image name, popped an NSLog in the segment you posted and it doesnt appear so I imagine it is not being executed? – Josh Boothe Apr 14 '13 at 18:24
  • @JoshBoothe let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28204/discussion-between-rob-and-josh-boothe) – Rob Apr 14 '13 at 18:24
0

You can certainly use custom images for an MKAnnotationView, see iOS MapKit custom pins.

Community
  • 1
  • 1
jszumski
  • 7,430
  • 11
  • 40
  • 53
0

Both MKAnnotationPinView and MKAnnotationView are subclasses of UIView and therefore will allow custom views.

Hemang
  • 26,840
  • 19
  • 119
  • 186
ennuikiller
  • 46,381
  • 14
  • 112
  • 137