【问题标题】:How to move a MKAnnotation without adding/removing it from the map?如何在不从地图中添加/删除的情况下移动 MKAnnotation?
【发布时间】:2011-01-16 09:41:51
【问题描述】:

是否可以移动 MKAnnotation 的坐标而不在地图中添加和删除注释?

【问题讨论】:

    标签: iphone objective-c mapkit mkmapview


    【解决方案1】:

    在 Swift 4.0 和 IOS 11.0 中,我只是将动态属性添加到 MKAnnotation 类的子类的坐标属性中,它可以工作:如果更新了 MKAnnotation 对象的坐标值,则 MapView 上的所有注释都会更新它们的位置:

    class CarAnnotation: NSObject, MKAnnotation {
        @objc dynamic var coordinate: CLLocationCoordinate2D
        //Add your custom code here
    }
    

    【讨论】:

    • 应该是公认的答案。我从来不知道这件事!你刚刚为我节省了很多时间。 ;)
    • 这是金色的
    【解决方案2】:

    子类MKPointAnnotation,它能够自动将地图上的注释视图更新到新坐标。

    【讨论】:

    • 感谢它的顺利工作。只需更新注释的坐标。
    • 在 Swift 中,请务必使用dynamic var coordinate,否则 KVO 不会自动运行
    【解决方案3】:

    在你更新了注解的坐标或其他一些属性之后,只需调用下面的 MKMapViewDelegate 方法来重绘你的注解:

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
    

    例如:

    myAnnotation.coordinate = CLLocationCoordinate2DMake([newLat doubleValue], [newLon doubleValue]);
    [self mapView:self.mapView viewForAnnotation:myAnnotation];
    

    【讨论】:

      【解决方案4】:

      大多数答案是基于您的注释是通过 MKPlacemark 扩展进行的。但是任何其他只实现 MKAnnotation 协议的对象(即标记的自定义图像)呢?它没有 setCoordinate 方法。所以这里是基于代码的答案,由100grams

      提供
          MKAnnotationView *av = [self.mapView viewForAnnotation:user];
          //user is an object which implements <MKAnnotation>
          // You will probably get your MKAnnotationView in your own way
          if (av){
              // here user returns CLLocationCoordinate2D coordinate  
              MKMapPoint mapPoint = MKMapPointForCoordinate([user getLastLocation]); 
              // converting mapPoint to CGPoint 
              CGPoint newPos;
              CGFloat zoomFactor =  self.mapView.visibleMapRect.size.width / self.mapView.bounds.size.width;
              newPos.x = mapPoint.x/zoomFactor;
              newPos.y = mapPoint.y/zoomFactor;
              // animation for annotation's move
              static NSString *POSITION_KEY=@"positionAnimation";
          static NSString *PATH_ANIMATION_KEY=@"position";
          if (MKMapRectContainsPoint(self.mapView.visibleMapRect, mapPoint)) {
              CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:PATH_ANIMATION_KEY];
              animation.fromValue = [NSValue valueWithCGPoint:av.center];
              animation.toValue = [NSValue valueWithCGPoint:newPos];  
              animation.duration = 0.3;
              animation.delegate = av;
              animation.fillMode = kCAFillModeForwards;
              [av.layer addAnimation:animation forKey:POSITION_KEY];
          }
              // moving view
              av.center = newPos;
      

      所以您基本上需要获取相应的 MKAnnotationView,这也可以通过所有注释的迭代来实现,并且它是新位置。我为所有这些创建了一个数组持有者(NSMutableArray *mapAnotaions),所以现在我可以像这样迭代:

      for (id annotation in mapAnnotaions) {call refresh method here for id}
      

      【讨论】:

      • :- 我清楚地理解你在上面的代码 sn-p 中提到的内容。我赞成你的回答。您能否解释一下如何在特定地图点停止动画 2 秒然后再次开始移动对象?
      • 关于暂停:我无法为您提供代码,但我想您可以使用 [NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:] 在地图点之间暂停。这也将使用户有机会在动画暂停时使用 GUI。
      • :- 如果我们需要在某个时间间隔后停止动画,上述方法可能会起作用。但是这里我们需要根据坐标值停止动画,然后在几秒钟后恢复。在这种情况下我们可以使用定时器来恢复动画,但是如何根据坐标值停止动画呢?
      【解决方案5】:

      只需使用 KVO:

      [annotation willChangeValueForKey:@"coordinate"];
      [annotation didChangeValueForKey:@"coordinate"];
      

      如果您的 MKAnnotation 有一个 setCoordinate 方法,只需在此处包含这些行:

      - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
          [self willChangeValueForKey:@"coordinate"];
          coordinate = newCoordinate;
          [self didChangeValueForKey:@"coordinate"];
      }
      

      【讨论】:

      • 或者如果你扩展 MKPointAnnotation 那么它已经有一个坐标属性,支持 KVO 并在地图上自动移动。
      【解决方案6】:

      确实可以在不删除和添加注释的情况下偏离路线。

      您需要观察 MKAnnotation 的坐标并在 MKAnnotationView 发生变化时更新它的位置。或者,您可以(这可能是更优雅的方式)派生出您自己的 MKAnnotation 和 MKAnnotationView 并使它们“可移动”。

      查看Moving-MKAnnotationView 的详细示例,该示例还为注释的位置设置动画。

      【讨论】:

        【解决方案7】:

        如果您保留对注释的引用,对坐标属性进行更改,然后再次将注释添加到地图,注释视图的位置将更新。您不需要移除注释(这会导致注释视图暂时消失)。然而,当注释坐标更新时,这不会给你一个很好的过渡。它也不会导致内存泄漏,也不会向地图添加多个相同的注释(如果您查看地图视图上的注释数量,当您重新添加注释时它保持不变)。

        【讨论】:

        • 这实际上是行不通的,如果我删除并添加它可以工作的注释。但是简单地修改坐标属性并使用mapView.addAnnotation(myAnnotation) 不会移动注释,但是如果我打印坐标,它们会有效地改变。我想知道为什么。
        【解决方案8】:

        我找到了一个非常简单的方法。我想顺利更新我的玩家的位置,而不需要删除然后重新添加玩家注释。这适用于 iOS4 之前的应用程序,它的作用是移动图钉并将地图居中到图钉的新位置:

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.5];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [player setCoordinate:aLoc.coordinate];
        [mapView setCenterCoordinate:aLoc.coordinate animated:NO];
        [UIView commitAnimations];
        

        这里是同样的事情,但使用 iOS4 推荐的块功能:

        [UIView animateWithDuration:0.5 animations:^{
            [player setCoordinate:aLoc.coordinate];
            [mapView setCenterCoordinate:aLoc.coordinate animated:NO];
        }];
        

        【讨论】:

        • 任何更新您的图钉位置的方法。对我来说,我有另一个对象向我的地图视图控制器发送一个新位置,然后我用它来更新我的玩家图钉的位置。但是您可以从外部来源接收新位置,或者通过用户触摸按钮或使用拖放等方式接收新位置。
        • 不知道为什么,但是这个方法让 MapView 自己重绘,所以我个人不喜欢它。
        • 这似乎有效。我只是在移动注释,而不是重置中心 - 但我没有得到任何 MapView 重绘。我确实遇到的一个问题(这也是另一个更复杂的解决方案的问题)是,如果您在动画阶段缩放,注释就会消失。它会在动画结束时重新出现,所以没什么大不了的。
        【解决方案9】:

        看看我的MapKitDragAndDrop 示例,它允许您在 iPhone OS 3 和 iOS 4 上更新 MKAnnotation 和移动 MKAnnotationView(将使用内置的拖动支持)。

        【讨论】:

          【解决方案10】:

          不知道是否更普遍,但如果您有自己的自定义 MKAnnotationView。

          我能够适应 Craig Spitzkoff 在http://spitzkoff.com/craig/?p=108 中记录的方法:

          1. 为您的自定义 MKAnnotationView 提供对您的 MKAnnotation 对象的引用
          2. 添加一个 updateCoordinates 方法 到 MKAnnotation 对象并调用 当你想改变位置时 注释
          3. 在自定义上调用 regionChanged MKAnnotationView 让它知道什么时候 重新定位自己(例如,当 MKAnnotation 已更新 坐标)
          4. 在 drawRect 上 您拥有的内部视图对象 自定义 MKAnnotationView 你可以 使用坐标重新定位 MKAnnotation(你拿着一个 参考)。

          您可能会进一步简化此方法 - 您可能不需要在所有情况下都使用内部视图对象。

          【讨论】:

          • 是的,这就是我想出的解决方案,但让 drawRect 确定它自己的框架似乎很奇怪。
          • 请问您能提供一个样品吗?
          【解决方案11】:

          似乎不可能更改 MKAnnotation 对象的坐标,然后将更改通知 MKMapView。

          但是,从地图中删除先前的注释,更改注释对象的坐标并将其添加回地图效果很好。

          [theMapView removeAnnotation:myAnnotation]; 
          [myAnnotation setLatitude:newLatitude];
          [theMapView addAnnotation:myAnnotation];
          

          你为什么不想这样做?

          【讨论】:

          • OP 要求这样做,对于许多用户来说,它更希望看到平稳过渡
          • 有可能,见我上面的回答。
          猜你喜欢
          • 2012-05-19
          • 2013-09-21
          • 2021-05-28
          • 2016-11-30
          • 2013-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-07
          相关资源
          最近更新 更多