Drag an annotation pin on a mapview
draggable, ios, iphone, mkannotation
Solution
First you have to create a custom annotation like this:
MyAnnotation.h
#import <MapKit/MapKit.h>
@interface MyAnnotation : NSObject <MKAnnotation>{
CLLocationCoordinate2D coordinate;
}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord;
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate;
@end
MyAnnotation.m
#import "MyAnnotation.h"
@implementation MyAnnotation
@synthesize coordinate;
- (NSString *)subtitle{
return nil;
}
- (NSString *)title{
return nil;
}
-(id)initWithCoordinate:(CLLocationCoordinate2D)coord {
coordinate=coord;
return self;
}
-(CLLocationCoordinate2D)coord
{
return coordinate;
}
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
coordinate = newCoordinate;
}
@end
After that, you just have to use your annotation like this:
// Assuming you have imported MyAnnotation.h and you have a self.map property pointing to a MKMapView
MyAnnotation *myPin = [[MyAnnotation alloc] initWithCoordinate:self.map.centerCoordinate]; // Or whatever coordinates...
[self.map addAnnotation:myPin];
Also, you have to return a view for your annotation. You can do so like this:
- (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id<MKAnnotation>) annotation {
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.map dequeueReusableAnnotationViewWithIdentifier: @"myPin"];
if (pin == nil) {
pin = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: @"myPin"] autorelease]; // If you use ARC, take out 'autorelease'
} else {
pin.annotation = annotation;
}
pin.animatesDrop = YES;
pin.draggable = YES;
return pin;
}
Then, once you have adopted the `MKMapViewDelegate` protocol in your controller, you grab the coordinates of a pin after dragging it like this:
- (void)mapView:(MKMapView *)mapView
annotationView:(MKAnnotationView *)annotationView
didChangeDragState:(MKAnnotationViewDragState)newState
fromOldState:(MKAnnotationViewDragState)oldState
{
if (newState == MKAnnotationViewDragStateEnding)
{
CLLocationCoordinate2D droppedAt = annotationView.annotation.coordinate;
NSLog(@"Pin dropped at %f,%f", droppedAt.latitude, droppedAt.longitude);
}
}
Problem
The annotation pin is draggable but I couldn't drop it to the destination location. The problem is how could I get the destination location's coordinate where i drop the annotation pin? Any method exist? Edit 1: The center of the annotation pin seems never changed where ever I drop the pin. ``` - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState { if (newState == MKAnnotationViewDragStateEnding) { NSLog(@"x is %f", annotationView.center.x); NSLog(@"y is %f", annotationView.center.y); CGPoint dropPoint = CGPointMake(annotationView.center.x, annotationView.center.y); CLLocationCoordinate2D newCoordinate = [self.mapView convertPoint:dropPoint toCoordinateFromView:annotationView.superview]; [annotationView.annotation setCoordinate:newCoordinate]; } } ``` Edit 2: Annotation.h ``` @property (nonatomic,readwrite,assign) CLLocationCoordinate2D coordinate; ``` Annotation.m ``` - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate { coordinate = newCoordinate; } ``` Edit 3: where ever I drag the pin, the NSLog out put of the droppedAt is always the same. ``` - (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState { if (newState == MKAnnotationViewDragStateEnding) { CLLocationCoordinate2D droppedAt = annotationView.annotation.coordinate; NSLog(@"Pin dropped at %f,%f", droppedAt.latitude, droppedAt.longitude); } } ``` Edit 4: Annotaion.m @dynamic startAddr; ``` - (CLLocationCoordinate2D)coordinate { coordinate.latitude = [self.startAddr.latitude doubleValue]; coordinate.longitude = [self.startAddr.longitude doubleValue]; return coordinate; } - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate { //I need to update the self.startAddr.latitude and longitude here. Problem solved. self.startAddr.latitude = [NSNumber numberWithDouble:newCoordinate.latitude]; self.startAddr.longitude = [NSNumber numberWithDouble:newCoordinate.longitude]; coordinate = newCoordinate; } ```