在地图视图上拖动注释图钉
Posted
技术标签:
【中文标题】在地图视图上拖动注释图钉【英文标题】:Drag an annotation pin on a mapview 【发布时间】:2012-05-30 19:19:44 【问题描述】:注释图钉是可拖动的,但我无法将其拖放到目标位置。问题是我怎样才能得到目标位置的坐标,我将注释销放在哪里?有什么方法吗?
编辑 1:
注释图钉的中心似乎从未在我放下图钉的地方改变。
- (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];
编辑 2:
Annotation.h
@property (nonatomic,readwrite,assign) CLLocationCoordinate2D coordinate;
注解.m
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
coordinate = newCoordinate;
编辑 3: 无论我在哪里拖动图钉,dropAt 的 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);
编辑 4:
注释.m @动态起始地址;
- (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;
【问题讨论】:
【参考方案1】:首先你必须像这样创建一个自定义注解:
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
之后,你只需要像这样使用你的注释:
// 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];
此外,您必须为注释返回一个视图。你可以这样做:
- (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;
然后,一旦你在控制器中采用了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);
【讨论】:
你在哪里设置了新坐标? 这就是您实现setCoordinate
方法的原因。来自Apple的文档-> 支持拖动的注解应该实现这个方法来更新注解的位置。
我更新了我的帖子中的坐标(只需编辑它)。但似乎不行。
注释会在您完成拖动时自动设置其坐标,这就是重点……您不必自己动手,只需获取新坐标即可。我希望这是有道理的。
要使此代码正常工作,您必须在 viewDidLoad 中将自己设置为地图委托。另外,添加“if ([annotation isKindOfClass:[MKUserLocation class]]) return nil;” viewForAnnotation 顶部附近【参考方案2】:
出乎意料,实现注释的 setCoordinates 方法,并在注释坐标发生变化时进行回调
edit :当注解移动时要小心它的 dragState 属性。
【讨论】:
【参考方案3】:你不想这样做吗:
设置注解委托, 那么
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
coordinate = newCoordinate;
if (self.delegate respondsToSelector:@selector(mapAnnotationCoordinateHaveChanged))
[self.delegate performSelector(@selector(mapAnnotationCoordinateHaveChanged))];
在您的委托中:
- (void) mapAnnotationCoordinateHaveChanged
//some coordinates update code
【讨论】:
【参考方案4】:- (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];
【讨论】:
【参考方案5】:Swift 2.2、Xcode 7.3.1 的示例:
创建采用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
现在,当图钉被拖动时,它会调用委托方法:
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView)
在这里,您可以检索新的结束坐标。
或者,您可以为自定义注释的 coordinate
属性的通知创建一个 userInfo
字典。观察者可以在收到通知后检索这些值。
【讨论】:
【参考方案6】:在 Swift 中,我的问题是 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()
【讨论】:
以上是关于在地图视图上拖动注释图钉的主要内容,如果未能解决你的问题,请参考以下文章