williamsandonz
williamsandonz

Reputation: 16420

MKMapView custom image not working

Trying to follow this tutorial: http://www.switchonthecode.com/tutorials/building-an-earthquake-monitor-for-iphone-using-mapkit

I have my Icons showing in all the right places (and right number) & the image is showing as well. (But it's always the same image. And that's because the conditional if(self.marker.type == "nzpost" isn't working, because type is always null (as are all the properties on the marker objects within initWithAnnotation()). For some reason the properties are all null.

Annotation view interface:

@interface PayMarkerAnnotationView : MKAnnotationView {
    PaymentMarker *marker;
}

@property (strong, nonatomic) IBOutlet PaymentMarker *marker;

@end

Init with annotation: (here is where self.marker.type should have a value.

- (id)initWithAnnotation:(id <MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
    if(self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
        self.backgroundColor = [UIColor clearColor];
        NSString* imageName = [[NSString alloc] init];

        if([self.marker.type isEqualToString:@"nzpost"]) {
            imageName = @"icon-map-post.png";
        } else {
            imageName = @"icon-map-incharge.png";
        }
        self.image = [UIImage imageNamed:imageName];
    }
    return self;
}

Mapview:

- (MKAnnotationView *)mapView:(MKMapView *)lmapView viewForAnnotation:(id <MKAnnotation>)annotation {
    PayMarkerAnnotationView *markerView = (PayMarkerAnnotationView *)[lmapView dequeueReusableAnnotationViewWithIdentifier:@"markerView"];
    if(markerView == nil) {
        markerView = [[PayMarkerAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"markerView"];
    }
    markerView.annotation = annotation;
    return markerView;
}

Adding my markers in

-(void)renderPaymentMarkers
{
    [self.map addAnnotations: nzPostMarkers];
    [self.map addAnnotations: inChargeMarkers];
}

Marker class:

@interface PaymentMarker : NSObject <MKAnnotation> {
    NSString* type;
    NSString* description;
    float latitude;
    float longitude;}

@property (nonatomic) NSString* description;
@property (nonatomic) NSString* type;
@property (nonatomic) float latitude;
@property (nonatomic) float longitude;

//MKAnnotation
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@end

Upvotes: 2

Views: 557

Answers (1)

user467105
user467105

Reputation:

The marker variable in PayMarkerAnnotationView is never set.

(I'm not sure why you've made its property an IBOutlet as well.)

It needs to be set in the initWithAnnotation method before you access it:

if (self = [super initWithAnnotation...
    //set marker equal to the annotation this view is being created for...
    marker = annotation;

    self.backgroundColor = [UIColor clearColor];
    ...

However, you don't need the marker variable in the first place.
MKAnnotationView already has an annotation property which gets set when you call super initWithAnnotation.

So in your initWithAnnotation, instead of this:

if([self.marker.type isEqualToString:@"nzpost"]) {

you could do this:

PaymentMarker *pm = (PaymentMarker *)self.annotation;
if([pm.type isEqualToString:@"nzpost"]) {

That should fix the main issue.


Another potential problem is that in viewForAnnotation, you are updating the view's annotation property directly in case the view is being re-used from another annotation.

This is fine (though it should be done in an else block) but the problem is that the view's image will not also update when annotation is updated.

So if the previous annotation that used the view was of type "nzpost" but the current annotation is of some other type, the view will still show the image for the previous annotation's type.

To fix this, here are two possible solutions:

  • Use a separate reuseIdentifier for each type (so two ids: "post" and "incharge"). This way, only views with the matching image will get re-used for the current annotation.
  • Override setAnnotation: in PayMarkerAnnotationView and update both the annotation and image properties. I prefer this solution.


Some other completely unrelated items...

This line:

NSString* imageName = [[NSString alloc] init];

doesn't make sense because the code later on just overwrites imageName with a new value. So the memory that was allocated is abandoned. Instead, just declare imageName:

NSString* imageName;

These properties:

@property (nonatomic) NSString* description;
@property (nonatomic) NSString* type;

should be declared with the copy attribute (the compiler should be complaining about this):

@property (nonatomic, copy) NSString* description;
@property (nonatomic, copy) NSString* type;

You may also want to change the name of the description property since you are overriding a property of the same name supplied by NSObject (unless that was your intention).

Upvotes: 1

Related Questions