I think those two are related and I'm probably doing something wrong here:
First I'm overriding viewForAnnotation - in order to put my custom Image
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
// we avoid changing the user's location blue point
if([annotation isKindOfClass: [MKUserLocation class]]) {
return nil;
}
else
{
static NSString *SFAnnotationIdentifier = @"SFAnnotationIdentifier";
MKPinAnnotationView* pinAnnotationView = (MKPinAnnotationView*)[self.mapToPin dequeueReusableAnnotationViewWithIdentifier:SFAnnotationIdentifier];
if (!pinAnnotationView)
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:SFAnnotationIdentifier];
UIImage *littleImage = [UIImage imageNamed:@"littleImage.png"];
// You may need to resize the image here.
annotationView.image = littleImage;
pinAnnotationView.draggable = true;
pinAnnotationView.canShowCallout = true;
pinAnnotationView.animatesDrop = true;
return annotationView;
}
else
{
pinAnnotationView.annotation = annotation;
}
return pinAnnotationView;
}
}
It seems that pinAnnotationView's draggable, canShowCallout and animatesDrop are not working.
Then, I'm calling my method in my viewDidLoad to set the Annotation
-(void) setAnnotation:(NSString*)lat : (NSString*)lng
{
_mapAnnotation = [[MKPointAnnotation alloc] init];
CLLocationCoordinate2D coordinateForPin;
coordinateForPin.latitude = [lat floatValue];
coordinateForPin.longitude = [lng floatValue];
[_mapAnnotation setCoordinate:coordinateForPin];
[_mapAnnotation setTitle:@"sometitle"];
[_mapToPin addAnnotation:_mapAnnotation];
}
It seems that [_mapAnnotation setTitle:@"sometitle"]; is not working anymore when I'm overriding viewForAnnotation.
Is this the right way to go? I have been browsing but didn't find any solution that could help. Any feedback would be appreciated.
The problem is the accidental reference to the wrong variable name. The pinAnnotationView
is nil
inside that if
statement, so setting properties with that nil
reference is a NOOP.
if (!pinAnnotationView) {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:SFAnnotationIdentifier];
...
annotationView.draggable = true; // not pinAnnotationView
annotationView.canShowCallout = true;
annotationView.animatesDrop = true;
return annotationView;
}
FWIW, if targeting iOS 10 or later, you can register your own class and move your annotation view configuration code into that subclass. Furthermore, in iOS 11 and later you do not need mapView:viewForAnnotation:
at all.
For example, in iOS 11 and later:
// MyAnnotationView.h
@import MapKit;
NS_ASSUME_NONNULL_BEGIN
@interface MyAnnotationView : MKPinAnnotationView
@end
NS_ASSUME_NONNULL_END
and
// MyAnnotationView.m
#import "MyAnnotationView.h"
@implementation MyAnnotationView
- (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self) {
...
self.draggable = true;
self.canShowCallout = true;
self.animatesDrop = true;
}
return self;
}
@end
And then, in your viewDidLoad
, you register this class.
- (void)viewDidLoad {
[super viewDidLoad];
[self.mapView registerClass:[MyAnnotationView class] forAnnotationViewWithReuseIdentifier:MKMapViewDefaultAnnotationViewReuseIdentifier];
...
}
You can then remove the mapView:viewForAnnotation:
implementation entirely.