ios 在地图视图上拖动注释图钉
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10733564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Drag an annotation pin on a mapview
提问by lu yuan
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
注释.h
@property (nonatomic,readwrite,assign) CLLocationCoordinate2D coordinate;
Annotation.m
注释.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:无论我在哪里拖动 pin,droppedAt 的 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;
}
回答by Alladinian
First you have to create a custom annotation like this:
首先,您必须像这样创建一个自定义注释:
MyAnnotation.h
我的注解.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 MKMapViewDelegateprotocol 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);
}
}
回答by CitronEvanescent
Out of the blue, implement the setCoordinates method of your annotation and make a callBAck when your annotation coordinates have changed
突然之间,实现注释的 setCoordinates 方法,并在注释坐标发生变化时进行回调
edit : beware of the dragState property of your annotation while its moving.
编辑:注意移动时注释的 dragState 属性。
回答by CitronEvanescent
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
}
回答by Bhavesh Nayi
- (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];
}
}
回答by leanne
Example for Swift 2.2, Xcode 7.3.1:
Swift 2.2、Xcode 7.3.1 的示例:
Create custom class adopting MKAnnotation protocol
(note: Swift doesn't have automatic notification for KVO-compliant properties, so I have added my own - this is not required):
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 }
使用 MKAnnotation 协议创建自定义类
(注意: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 } }将 pin 视图声明为可拖动:
// 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:
现在,当拖动 pin 时,它会调用委托方法:
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView)
Here, you can retrieve the new end coordinates.
在这里,您可以检索新的结束坐标。
Alternatively, you could create a userInfodictionary for the custom annotation's coordinateproperty's notifications. Observers could then retrieve the values upon receipt of the notification.
或者,您可以userInfo为自定义注释的coordinate属性通知创建一个字典。观察者可以在收到通知后检索这些值。
回答by Kevin Delord
In Swift my problem was that the coordinateattribute was a letin my subclass and not a varas 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()
}
}

