简体   繁体   English

在地图视图上拖动注释图钉

[英]Drag an annotation pin on a mapview

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: 编辑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: 编辑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. 编辑3:在我将销拖到哪里的地方,dropAtAt的NSLog输出始终相同。

- (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: 编辑4:

Annotaion.m @dynamic startAddr; 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; 
}

First you have to create a custom annotation like this: 首先,您必须创建一个自定义注释,如下所示:

MyAnnotation.h MyAnnotation.h

#import <MapKit/MapKit.h>

@interface MyAnnotation : NSObject <MKAnnotation>{

    CLLocationCoordinate2D coordinate;

}
- (id)initWithCoordinate:(CLLocationCoordinate2D)coord;
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate;
@end

MyAnnotation.m 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: 然后,一旦在控制器中采用了MKMapViewDelegate协议,就可以像这样拖动它来获取销的坐标:

- (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);
    }
}

Out of the blue, implement the setCoordinates method of your annotation and make a callBAck when your annotation coordinates have changed 突然,实现注释的setCoordinates方法,并在注释坐标发生更改时进行callBAck

edit : beware of the dragState property of your annotation while its moving. 编辑:注意注释在移动时的dragState属性。

Don't you wan't to do this : 你不这样做吗:

Setting the annotation delegate, then 设置注释委托,然后

- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
   coordinate = newCoordinate; 
   if (self.delegate respondsToSelector:@selector(mapAnnotationCoordinateHaveChanged))
    [self.delegate performSelector(@selector(mapAnnotationCoordinateHaveChanged))];
}

In your delegate : 在您的代表中:

- (void) mapAnnotationCoordinateHaveChanged{
 //some coordinates update code
}
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
    MKAnnotationView *a = [ [ MKAnnotationView alloc ] initWithAnnotation:annotation reuseIdentifier:@"currentloc"];
    //  a.title = @"test";
    if ( a == nil )
        a = [ [ MKAnnotationView alloc ] initWithAnnotation:annotation reuseIdentifier: @"currentloc" ];

    NSLog(@"%f",a.annotation.coordinate.latitude);
    NSLog(@"%f",a.annotation.coordinate.longitude);

    CLLocation* currentLocationMap = [[[CLLocation alloc] initWithLatitude:a.annotation.coordinate.latitude longitude:a.annotation.coordinate.longitude] autorelease];
    [self coordinatesToDMS:currentLocationMap];


    MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:a reuseIdentifier:@"currentloc"];
    if(a.annotation.coordinate.longitude == mapView.userLocation.coordinate.longitude ||  a.annotation.coordinate.latitude == mapView.userLocation.coordinate.latitude  )
    {
        if ([annotation isKindOfClass:MKUserLocation.class])
        {
            //user location view is being requested,
            //return nil so it uses the default which is a blue dot...
            return nil;
        }       
        //a.image = [UIImage imageNamed:@"userlocation.png"];
        //a.pinColor=[UIColor redColor];
    }
    else 
    {

        // annView.image =[UIImage imageNamed:@"map-pin.png"];
        //PinFirst=FALSE;
        //annView.pinColor = [UIColor redColor];
        // annView.annotation=annotation;
    }

    annView.animatesDrop = YES;
    annView.draggable = YES;

    annView.canShowCallout = YES;

    return annView;
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    NSLog(@"map Drag");
}

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
fromOldState:(MKAnnotationViewDragState)oldState;
{
    NSLog(@"pin Drag");

    if (newState == MKAnnotationViewDragStateEnding)
    {
        CLLocationCoordinate2D droppedAt = view.annotation.coordinate;
        NSLog(@"Pin dropped at %f,%f", droppedAt.latitude, droppedAt.longitude);

        CLLocation* draglocation = [[[CLLocation alloc] initWithLatitude:droppedAt.latitude longitude:droppedAt.longitude] autorelease];



    }
}

Example for Swift 2.2, Xcode 7.3.1: Swift 2.2,Xcode 7.3.1的示例:

  • Create custom class adopting MKAnnotation protocol 创建采用MKAnnotation协议的自定义类

    (note: Swift doesn't have automatic notification for KVO-compliant properties, so I have added my own - this is not required): (注意:Swift没有自动通知符合KVO的属性,因此我添加了自己的通知-这不是必需的):

     import MapKit class MyAnnotation: NSObject, MKAnnotation { // MARK: - Required KVO-compliant Property var coordinate: CLLocationCoordinate2D { willSet(newCoordinate) { let notification = NSNotification(name: "VTAnnotationWillSet", object: nil) NSNotificationCenter.defaultCenter().postNotification(notification) } didSet { let notification = NSNotification(name: "VTAnnotationDidSet", object: nil) NSNotificationCenter.defaultCenter().postNotification(notification) } } // MARK: - Required Initializer init(coordinate: CLLocationCoordinate2D) { self.coordinate = coordinate } } 
  • Declare pin view as draggable: 将图钉视图声明为可拖动:

     // MARK: - MKMapViewDelegate Actions func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: pinViewReuseIdentifier) pinView.draggable = true return pinView } 

Now, when the pin is dragged, it invokes the delegate method: 现在,当拖动图钉时,它将调用委托方法:

func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView)

Here, you can retrieve the new end coordinates. 在这里,您可以检索新的终点坐标。


Alternatively, you could create a userInfo dictionary for the custom annotation's coordinate property's notifications. 另外,您可以为自定义注释的coordinate属性的通知创建一个userInfo字典。 Observers could then retrieve the values upon receipt of the notification. 然后,观察者可以在收到通知后检索值。

In Swift my problem was that the coordinate attribute was a let in my subclass and not a var as it is in the MKAnnotation . 在斯威夫特我的问题是, coordinate属性是一个let我的子类,而不是一个var ,因为它是在MKAnnotation

class MyAnnotation  : NSObject, MKAnnotation {

    let title       : String?
    let subtitle    : String?
    var coordinate  : CLLocationCoordinate2D

    init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) {
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate
        super.init()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM