1
votes

I'm building an OSX application that uses Mapkit, and I'm trying to get a callout to appear when I click on an MKAnnotationView on my map. To do this I'm implementing the MKMapViewDelegate, and the following function :

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[LocationPin class]]) {
    LocationPin *returnPin = (LocationPin *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"LocationPin"];
    if (!returnPin){
        returnPin = [LocationPin createLocationPinForMapView:mapView annotation:annotation];
    }
    returnPin.title = annotation.title;
    NSButton *rightButton = [[NSButton alloc] initWithFrame:NSMakeRect(0.0, 0.0, 100.0, 80.0)];
    [rightButton setTitle:@"Info"];
    [rightButton setBezelStyle:NSShadowlessSquareBezelStyle];
    returnPin.annotation = annotation;
    returnPin.canShowCallout = YES;
    returnPin.rightCalloutAccessoryView = rightButton;
    return returnPin;
    }
    return nil;
    }

The function runs fine everytime I put a new pin down, and I made sure the titles of the pins are not empty or null, but the callout still is not showing up. Anybody have any ideas?

EDIT: After looking through Anna's response, I realized I misunderstood how to implement the MKAnnotation protocol. I've deleted my LocationPin class, which inherited from MKAnnotationView, and instead added the following class to represent my custom MKAnnotation, with a class inside of it to generate a custom MKAnnotationView:

@implementation LocationAnnotation:

-(id)initWithTitle:(NSString *)newTitle Location:(CLLocationCoordinate2D)location     {
    self = [super init];

    if(self) {
    _title = newTitle;
    _coordinate = location;
    }

    return self;
}

- (MKAnnotationView *)annotationView {

    MKAnnotationView *annotationView = [[MKAnnotationView alloc]initWithAnnotation:self reuseIdentifier:@"LocAnno"];
    annotationView.enabled = YES;
    annotationView.canShowCallout = YES;
    annotationView.image = [NSImage imageNamed:@"dvd"];

    NSButton *rightButton = [[NSButton alloc] initWithFrame:NSMakeRect(0.0, 0.0, 100.0, 80.0)];
    [rightButton setTitle:@"Info"];
    [rightButton setBezelStyle:NSShadowlessSquareBezelStyle];

    annotationView.rightCalloutAccessoryView = rightButton;

    return annotationView;
}

@end

I've also changed the MKMapViewDelegate function the following way now:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[LocationAnnotation class]]) {

        LocationAnnotation *anno = (LocationAnnotation *)annotation;
        MKAnnotationView *returnPin = [mapView dequeueReusableAnnotationViewWithIdentifier:@"LocAnno"];
        if (!returnPin){
            returnPin = anno.annotationView;
        }
        else {
            returnPin.annotation = annotation;
        }
        return returnPin;
    }
    return nil;
}

But the callout still is not appearing. Any help is appreciated.

Edit 2: As requested, LocationAnnotation.h:

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface LocationAnnotation : NSObject <MKAnnotation>

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

-(id)initWithTitle:(NSString *)newTitle Location:(CLLocationCoordinate2D)location;
-(MKAnnotationView *)annotationView;



@end
1
The code is checking if annotation is of type LocationPin and then creates returnPin which is also of type LocationPin and returns that as the MKAnnotationView? So the LocationPin class is both an annotation model object and a subclass of MKAnnotationView? That seems confusing and odd. Show how the annotations are created and added to the map.user467105
Turns out I misunderstood the MKAnnotation protocol, and that may have been causing some confusion. The callouts still are not appearing, but I've designed the classes a little bit better (See the edit). As for how annotations are created and added to the map, my class that inherits from MKMapView, I have a MouseDown handler that gets the coordinates of a click on the map, and creates and adds a new annotation using [[LocationAnnotation alloc]initWithTitle:@"LocationAnno" Location:coord]user2539621
It looks like there may not be a proper connection between the instance variable _title and the title property. Even though _title is set in the init method, that might not be the backing instance variable that the title property is using (and so title remains nil). Can you please show the full LocationAnnotation.h and .m files including all instance variables, properties, and synthesizes?user467105
So there's no explicit ivar declared _title and no @synthesize? Try changing _title = newTitle; to _title = [newTitle copy];. After the alloc+initWithTitle line, NSLog the title and see what it says: NSLog(@"title=[%@]", ann.title);.user467105
Strange, problem must be in some code not shown. Last attempt: Try removing or commenting out the whole viewForAnnotation delegate method. The map view should then create a default red pin. See if tapping on it shows the callout.user467105

1 Answers

1
votes

I figured out what was wrong. I was subclassing MKMapView, which is apparently not recommended by Apple, as it can cause some unwanted behavior.