【问题标题】: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; 
}

【问题讨论】:

    标签: iphone ios draggable mkannotation


    【解决方案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()
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-06-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-07-17
              • 1970-01-01
              相关资源
              最近更新 更多