iOS MapKit拖动注释(MKAnnotationView)不再平移地图 [英] iOS MapKit dragged annotations (MKAnnotationView) no longer pan with map

查看:217
本文介绍了iOS MapKit拖动注释(MKAnnotationView)不再平移地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习在我初出茅庐的iOS应用程序中使用MapKit。我正在使用我的一些模型实体作为注释(将< MKAnnotation> 协议添加到其头文件中)。我还创建自定义MKAnnotationViews并将 draggable 属性设置为 YES

I'm learning to use MapKit in my fledgling iOS app. I'm using some of my model entities as annotations (added the <MKAnnotation> protocol to their header file). I also create custom MKAnnotationViews and set the draggable property to YES.

我的模型对象有一个位置属性,这是一个 CLLocation * 。为了符合< MKAnnotation> 协议,我在该对象中添加了以下内容:

My model object has a location property, which is a CLLocation*. To conform to the <MKAnnotation> protocol, I added the following to that object:

- (CLLocationCoordinate2D) coordinate {
    return self.location.coordinate;
}

- (void) setCoordinate:(CLLocationCoordinate2D)newCoordinate {
    CLLocation* newLocation = [[CLLocation alloc]
        initWithCoordinate: newCoordinate
        altitude: self.location.altitude
        horizontalAccuracy: self.location.horizontalAccuracy
        verticalAccuracy: self.location.verticalAccuracy
        timestamp: nil];
    self.location = newLocation;
}

- (NSString*) title {
    return self.name;
}

- (NSString*) subtitle {
    return self.serialID;
}

所以,我有4个必需的方法。而且他们非常直截了当。当我在 MKAnnotationView @draggable 属性中读取苹果文档时,它会显示以下内容:

So, I have the 4 required methods. And they're pretty straightforward. When I read the apple docs on MKAnnotationView and the @draggable property, it says the following:


将此属性设置为YES会使用户可以拖动注释。如果是,则关联的注释对象还必须实现setCoordinate:方法。此属性的默认值为NO。

Setting this property to YES makes an annotation draggable by the user. If YES, the associated annotation object must also implement the setCoordinate: method. The default value of this property is NO.

在其他地方, MKAnnotation docs说:

And elsewhere, the MKAnnotation docs say:


您对此属性的实现必须符合键值观察(KVO)。有关如何实现对KVO的支持的更多信息,请参阅键值观察编程指南。

Your implementation of this property must be key-value observing (KVO) compliant. For more information on how to implement support for KVO, see Key-Value Observing Programming Guide.

我已阅读(简要)文档,我根本不清楚我应该做些什么才能实现坐标,这是我从 location property本身就是一个合适的属性。

I have read that (brief) document, and it is not clear at all to me what I'm supposed to do to accomplish that so that the coordinate, which I'm deriving from my location property is a proper property in and of itself.

但我有理由相信它不能正常工作。当我拖动它时,它会移动,但是当我平移地图时它不再重新定位。

But I'm reasonably sure it's not working correctly. When I drag the pin, it moves, but then it no longer relocates when I pan the map.

更新

所以我试着玩MKPinAnnotationView股票。为此,我只是注释掉了我的委托的 mapView:viewForAnnotation:方法。我发现默认情况下这些都不可拖动。我将 mapView:didAddAnnotationViews:添加到我的委托,将添加的视图的 draggable 属性设置为

So I tried playing with the stock MKPinAnnotationView. To do this, I simply commented out my delegate's mapView:viewForAnnotation: method. I discovered that these aren't draggable by default. I added the mapView:didAddAnnotationViews: to my delegate to set the draggable property of the added views to YES.

一旦这样配置,正如John Estropia在下面暗示的Pin视图似乎工作正常。我决定使用 mapView:annotationView:didChangeDragState:fromOldState:委托钩子来仔细看看发生了什么:

Once configured thus, the Pin views, as hinted by John Estropia below, seem to work fine. I decided to use the mapView:annotationView:didChangeDragState:fromOldState: delegate hook to get a closer look at what is going on:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState {
    NSArray* states = @[@"None", @"Starting", @"Dragging", @"Cancelling", @"Ending"];
    NSLog(@"dragStateChangeFrom: %@ to: %@", states[oldState], states[newState]);
}

对于库存引脚,会看到如下所示的日志输出:

For the stock pins, one will see log output that looks like this:

2014-02-05 09:07:45.924 myValve[1781:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:07:46.249 myValve[1781:60b] dragStateChangeFrom: Starting to: Dragging
2014-02-05 09:07:47.601 myValve[1781:60b] dragStateChangeFrom: Dragging to: Ending
2014-02-05 09:07:48.006 myValve[1781:60b] dragStateChangeFrom: Ending to: None

看起来很合乎逻辑。但是,如果切换到配置的 MKAnnotationView ,您将看到的输出如下:

Which looks pretty logical. But if you switch to the configured MKAnnotationView, the output you will see looks like:

2014-02-05 09:09:41.389 myValve[1791:60b] dragStateChangeFrom: None to: Starting
2014-02-05 09:09:45.451 myValve[1791:60b] dragStateChangeFrom: Starting to: Ending

它错过了两次转换,从开始到拖动,从结束到无。

It misses TWO transitions, from Starting to Dragging, and from Ending to None.

所以我开始怀疑我需要做一些与属性不同的事情。但我仍然感到沮丧,为什么这不起作用。

So I begin to be skeptical that I need to do something different with properties. But I'm still frustrated with why this won't work.

更新2

我创建了自己的 Annotation 对象,以支持我的模型对象,它可以具有属性 coordinate 属性。行为保持不变。它似乎与 MKAnnotationView 有关。

I created my own Annotation object to stand between my model objects, which could have a property coordinate property. The behavior remains the same. It seems to be something with the MKAnnotationView.

推荐答案

有很多有关如何使用委托方法的示例 mapView:viewForAnnotation:显示设置 MKAnnotationView 。但是,仅仅因为您将 MKAnnotationView 实例的可拖动属性设置为 YES ,您仍然需要编写一些代码来帮助它转换某些状态。 MapKit将负责将您的实例的 dragState 移动到 MKAnnotationViewDragStateStarting MKAnnotationViewDragStateEnding ,但它不会执行其他转换。您可以在关于子类化 MKAnnotationView 的文档说明中看到这一点,并且需要覆盖`setDragState:animated:'

There are lots of examples about how to use the delegate method mapView:viewForAnnotation: that show setting up an MKAnnotationView. But what is not as obvious is that just because you set the draggable property of your MKAnnotationView instance to YES, you still have to write some code to help it transition some of the states. MapKit will take care of moving your instance's dragState to MKAnnotationViewDragStateStarting and MKAnnotationViewDragStateEnding, but it will not do the other transitions. You see hints of this in the docs notes about subclassing MKAnnotationView and the need to override the `setDragState:animated:'

当拖动状态更改为MKAnnotationViewDragStateStarting时,将状态设置为MKAnnotationViewDragStateDragging。如果执行动画以指示拖动的开始,并且动画参数为YES,则在更改状态之前执行该动画。

When the drag state changes to MKAnnotationViewDragStateStarting, set the state to MKAnnotationViewDragStateDragging. If you perform an animation to indicate the beginning of a drag, and the animated parameter is YES, perform that animation before changing the state.

当状态更改为MKAnnotationViewDragStateCanceling时或MKAnnotationViewDragStateEnding,将状态设置为MKAnnotationViewDragStateNone。如果在拖动结束时执行动画,并且动画参数为YES,则应在更改状态之前执行该动画。

When the state changes to either MKAnnotationViewDragStateCanceling or MKAnnotationViewDragStateEnding, set the state to MKAnnotationViewDragStateNone. If you perform an animation at the end of a drag, and the animated parameter is YES, you should perform that animation before changing the state.

在这种情况下,我不是子类,但似乎 MKAnnotationView 仍然难以自己进行转换。所以你必须实现委托的 mapView:annotationView:didChangeDragState:fromOldState:方法。例如

In this case, I'm not subclassing, but it seems that MKAnnotationView still struggles to make the transitions on its own. So you have to implement the delegate's mapView:annotationView:didChangeDragState:fromOldState: method. E.g.

- (void)mapView:(MKMapView *)mapView
        annotationView:(MKAnnotationView *)annotationView
        didChangeDragState:(MKAnnotationViewDragState)newState
        fromOldState:(MKAnnotationViewDragState)oldState {
    if (newState == MKAnnotationViewDragStateStarting) {
        annotationView.dragState = MKAnnotationViewDragStateDragging;
    }
    else if (newState == MKAnnotationViewDragStateEnding || newState == MKAnnotationViewDragStateCanceling) {
        annotationView.dragState = MKAnnotationViewDragStateNone;}
    }
}

这样可以适当地完成任务,这样当您在拖动注释后平移地图时,注释会随着平移移动。

This allows things to complete appropriately, so that when you pan the map after dragging the annotation, the annotation moves with the pan.

这篇关于iOS MapKit拖动注释(MKAnnotationView)不再平移地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆